source: trunk/minix/drivers/dp8390/dp8390.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 50.6 KB
Line 
1/*
2 * dp8390.c
3 *
4 * This file contains a ethernet device driver for NS dp8390 based ethernet
5 * cards.
6 *
7 * The valid messages and their parameters are:
8 *
9 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
10 * |------------+----------+---------+----------+---------+---------|
11 * | HARDINT | | | | | |
12 * |------------|----------|---------|----------|---------|---------|
13 * | DL_WRITE | port nr | proc nr | count | mode | address |
14 * |------------|----------|---------|----------|---------|---------|
15 * | DL_WRITEV | port nr | proc nr | count | mode | address |
16 * |------------|----------|---------|----------|---------|---------|
17 * | DL_READ | port nr | proc nr | count | | address |
18 * |------------|----------|---------|----------|---------|---------|
19 * | DL_READV | port nr | proc nr | count | | address |
20 * |------------|----------|---------|----------|---------|---------|
21 * | DL_INIT | port nr | proc nr | mode | | address |
22 * |------------|----------|---------|----------|---------|---------|
23 * | DL_GETSTAT | port nr | proc nr | | | address |
24 * |------------|----------|---------|----------|---------|---------|
25 * | DL_STOP | port_nr | | | | |
26 * |------------|----------|---------|----------|---------|---------|
27 *
28 * The messages sent are:
29 *
30 * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
31 * |-------------+----------+---------+----------+---------+---------|
32 * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
33 * |-------------+----------+---------+----------+---------+---------|
34 *
35 * m_type m3_i1 m3_i2 m3_ca1
36 * |-------------+---------+-----------+---------------|
37 * |DL_INIT_REPLY| port nr | last port | ethernet addr |
38 * |-------------+---------+-----------+---------------|
39 *
40 * Created: before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
41 *
42 * Modified Mar 10 1994 by Philip Homburg
43 * Become a generic dp8390 driver.
44 *
45 * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
46 * Added support for 3c503 boards.
47 */
48
49#include "../drivers.h"
50
51#include <stdlib.h>
52#include <minix/com.h>
53#include <net/hton.h>
54#include <net/gen/ether.h>
55#include <net/gen/eth_io.h>
56#include "assert.h"
57
58#include "local.h"
59#include "dp8390.h"
60
61#define DE_PORT_NR 3
62
63static dpeth_t de_table[DE_PORT_NR];
64static u16_t eth_ign_proto;
65static char *progname;
66
67/* Configuration */
68typedef struct dp_conf
69{
70 port_t dpc_port;
71 int dpc_irq;
72 phys_bytes dpc_mem;
73 char *dpc_envvar;
74} dp_conf_t;
75
76dp_conf_t dp_conf[]= /* Card addresses */
77{
78 /* I/O port, IRQ, Buffer address, Env. var. */
79 { 0x280, 3, 0xD0000, "DPETH0" },
80 { 0x300, 5, 0xC8000, "DPETH1" },
81 { 0x380, 10, 0xD8000, "DPETH2" },
82};
83
84/* Test if dp_conf has exactly DE_PORT_NR entries. If not then you will see
85 * the error: "array size is negative".
86 */
87extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
88
89/* Card inits configured out? */
90#if !ENABLE_WDETH
91#define wdeth_probe(dep) (0)
92#endif
93#if !ENABLE_NE2000
94#define ne_probe(dep) (0)
95#endif
96#if !ENABLE_3C503
97#define el2_probe(dep) (0)
98#endif
99
100/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
101 * on writes to the CR register. Additional CR_STAs do not appear to hurt
102 * genuine dp8390s
103 */
104#define CR_EXTRA CR_STA
105
106#if ENABLE_PCI
107_PROTOTYPE( static void pci_conf, (void) );
108#endif
109_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
110 int vectored) );
111_PROTOTYPE( static void do_vread, (message *mp, int vectored) );
112_PROTOTYPE( static void do_init, (message *mp) );
113_PROTOTYPE( static void do_int, (dpeth_t *dep) );
114_PROTOTYPE( static void do_getstat, (message *mp) );
115_PROTOTYPE( static void do_getname, (message *mp) );
116_PROTOTYPE( static void do_stop, (message *mp) );
117_PROTOTYPE( static void dp_init, (dpeth_t *dep) );
118_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep) );
119_PROTOTYPE( static void dp_reinit, (dpeth_t *dep) );
120_PROTOTYPE( static void dp_reset, (dpeth_t *dep) );
121_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep) );
122_PROTOTYPE( static void dp_recv, (dpeth_t *dep) );
123_PROTOTYPE( static void dp_send, (dpeth_t *dep) );
124_PROTOTYPE( static void dp8390_stop, (void) );
125_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
126 size_t offset, size_t size, void *dst) );
127_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
128 size_t offset, size_t size, void *dst) );
129_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
130 size_t offset, size_t size, void *dst) );
131_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
132 int length) );
133_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
134 vir_bytes offset, int nic_addr, vir_bytes count) );
135_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
136 iovec_dat_t *iovp, vir_bytes offset,
137 int nic_addr, vir_bytes count) );
138_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
139 iovec_dat_t *iovp, vir_bytes offset,
140 int nic_addr, vir_bytes count) );
141_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
142 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
143_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
144 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
145_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
146 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
147_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp) );
148_PROTOTYPE( static void conf_hw, (dpeth_t *dep) );
149_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) );
150_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
151_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block) );
152_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
153_PROTOTYPE( static void get_userdata, (int user_proc,
154 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
155_PROTOTYPE( static void put_userdata, (int user_proc,
156 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
157_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size) );
158_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size) );
159_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
160 vir_bytes buf, size_t size) );
161_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
162 vir_bytes buf, size_t size) );
163_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
164 vir_bytes buf, size_t size) );
165_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
166 vir_bytes buf, size_t size) );
167
168/*===========================================================================*
169 * dpeth_task *
170 *===========================================================================*/
171int main(int argc, char *argv[])
172{
173 message m;
174 int i, irq, r, tasknr;
175 dpeth_t *dep;
176 long v;
177
178 if (argc < 1)
179 {
180 panic("DP8390",
181 "A head which at this time has no name", NO_NUM);
182 }
183 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
184
185 env_setargs(argc, argv);
186
187 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
188 {
189 strcpy(dep->de_name, "dp8390#0");
190 dep->de_name[7] += i;
191 }
192
193 v= 0;
194 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
195 eth_ign_proto= htons((u16_t) v);
196
197 /* Try to notify inet that we are present (again) */
198 r = _pm_findproc("inet", &tasknr);
199 if (r == OK)
200 notify(tasknr);
201
202 while (TRUE)
203 {
204 if ((r= receive(ANY, &m)) != OK)
205 panic("", "dp8390: receive failed", r);
206
207 switch (m.m_type)
208 {
209 case DEV_PING: notify(m.m_source); continue;
210 case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
211 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
212 case DL_READ: do_vread(&m, FALSE); break;
213 case DL_READV: do_vread(&m, TRUE); break;
214 case DL_INIT: do_init(&m); break;
215 case DL_GETSTAT: do_getstat(&m); break;
216 case DL_GETNAME: do_getname(&m); break;
217 case DL_STOP: do_stop(&m); break;
218 case HARD_INT:
219 for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
220 {
221 if (dep->de_mode != DEM_ENABLED)
222 continue;
223 assert(dep->de_flags & DEF_ENABLED);
224 irq= dep->de_irq;
225 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
226 if (dep->de_int_pending || 1)
227 {
228 dep->de_int_pending= 0;
229 dp_check_ints(dep);
230 do_int(dep);
231 r= sys_irqenable(&dep->de_hook);
232 if (r != OK)
233 {
234 panic("DP8390",
235 "unable enable interrupts", r);
236 }
237 }
238 }
239 break;
240 case SYS_SIG: {
241 sigset_t sigset = m.NOTIFY_ARG;
242 if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
243 break;
244 }
245 case SYN_ALARM:
246 printf("dp8390: strange, got SYN_ALARM\n");
247 break;
248 case PROC_EVENT:
249 break;
250 default:
251 panic("", "dp8390: illegal message", m.m_type);
252 }
253 }
254}
255
256#if 0
257/*===========================================================================*
258 * dp8390_dump *
259 *===========================================================================*/
260void dp8390_dump()
261{
262 dpeth_t *dep;
263 int i, isr;
264
265 printf("\n");
266 for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
267 {
268#if XXX
269 if (dep->de_mode == DEM_DISABLED)
270 printf("dp8390 port %d is disabled\n", i);
271 else if (dep->de_mode == DEM_SINK)
272 printf("dp8390 port %d is in sink mode\n", i);
273#endif
274
275 if (dep->de_mode != DEM_ENABLED)
276 continue;
277
278 printf("dp8390 statistics of port %d:\n", i);
279
280 printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
281 printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
282 printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
283
284 printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
285 printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
286 printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
287
288 printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
289 printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
290 printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
291
292 printf("collision :%8ld\t", dep->de_stat.ets_collision);
293 printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
294 printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
295
296 printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
297 printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
298 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
299
300 printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
301
302 isr= inb_reg0(dep, DP_ISR);
303 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
304 inb_reg0(dep, DP_ISR), dep->de_flags);
305 }
306}
307#endif
308
309/*===========================================================================*
310 * dp8390_stop *
311 *===========================================================================*/
312static void dp8390_stop()
313{
314 message mess;
315 int i;
316
317 for (i= 0; i<DE_PORT_NR; i++)
318 {
319 if (de_table[i].de_mode != DEM_ENABLED)
320 continue;
321 mess.m_type= DL_STOP;
322 mess.DL_PORT= i;
323 do_stop(&mess);
324 }
325}
326
327#if ENABLE_PCI
328/*===========================================================================*
329 * pci_conf *
330 *===========================================================================*/
331static void pci_conf()
332{
333 int i, h;
334 char *envvar;
335 struct dpeth *dep;
336 static char envfmt[] = "*:d.d.d";
337 long v;
338 static int first_time= 1;
339
340 if (!first_time)
341 return;
342 first_time= 0;
343
344 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
345 {
346 envvar= dp_conf[i].dpc_envvar;
347 if (!(dep->de_pci= env_prefix(envvar, "pci")))
348 continue; /* no PCI config */
349 v= 0;
350 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
351 dep->de_pcibus= v;
352 v= 0;
353 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
354 dep->de_pcidev= v;
355 v= 0;
356 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
357 dep->de_pcifunc= v;
358 }
359
360 for (h= 1; h >= 0; h--) {
361 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
362 {
363 if (!dep->de_pci)
364 continue;
365 if (((dep->de_pcibus | dep->de_pcidev |
366 dep->de_pcifunc) != 0) != h)
367 {
368 continue;
369 }
370 if (!rtl_probe(dep))
371 dep->de_pci= -1;
372 }
373 }
374}
375#endif /* ENABLE_PCI */
376
377/*===========================================================================*
378 * do_vwrite *
379 *===========================================================================*/
380static void do_vwrite(mp, from_int, vectored)
381message *mp;
382int from_int;
383int vectored;
384{
385 int port, count, size;
386 int sendq_head;
387 dpeth_t *dep;
388
389 port = mp->DL_PORT;
390 count = mp->DL_COUNT;
391 if (port < 0 || port >= DE_PORT_NR)
392 panic("", "dp8390: illegal port", port);
393 dep= &de_table[port];
394 dep->de_client= mp->DL_PROC;
395
396 if (dep->de_mode == DEM_SINK)
397 {
398 assert(!from_int);
399 dep->de_flags |= DEF_PACK_SEND;
400 reply(dep, OK, FALSE);
401 return;
402 }
403 assert(dep->de_mode == DEM_ENABLED);
404 assert(dep->de_flags & DEF_ENABLED);
405 if (dep->de_flags & DEF_SEND_AVAIL)
406 panic("", "dp8390: send already in progress", NO_NUM);
407
408 sendq_head= dep->de_sendq_head;
409 if (dep->de_sendq[sendq_head].sq_filled)
410 {
411 if (from_int)
412 panic("", "dp8390: should not be sending\n", NO_NUM);
413 dep->de_sendmsg= *mp;
414 dep->de_flags |= DEF_SEND_AVAIL;
415 reply(dep, OK, FALSE);
416 return;
417 }
418 assert(!(dep->de_flags & DEF_PACK_SEND));
419
420 if (vectored)
421 {
422 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
423 (count > IOVEC_NR ? IOVEC_NR : count) *
424 sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
425 dep->de_write_iovec.iod_iovec_s = count;
426 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
427 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
428
429 dep->de_tmp_iovec = dep->de_write_iovec;
430 size = calc_iovec_size(&dep->de_tmp_iovec);
431 }
432 else
433 {
434 dep->de_write_iovec.iod_iovec[0].iov_addr =
435 (vir_bytes) mp->DL_ADDR;
436 dep->de_write_iovec.iod_iovec[0].iov_size =
437 mp->DL_COUNT;
438 dep->de_write_iovec.iod_iovec_s = 1;
439 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
440 dep->de_write_iovec.iod_iovec_addr = 0;
441 size= mp->DL_COUNT;
442 }
443 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
444 {
445 panic("", "dp8390: invalid packet size", size);
446 }
447 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
448 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
449 size);
450 dep->de_sendq[sendq_head].sq_filled= TRUE;
451 if (dep->de_sendq_tail == sendq_head)
452 {
453 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
454 outb_reg0(dep, DP_TBCR1, size >> 8);
455 outb_reg0(dep, DP_TBCR0, size & 0xff);
456 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
457 }
458 else
459 dep->de_sendq[sendq_head].sq_size= size;
460
461 if (++sendq_head == dep->de_sendq_nr)
462 sendq_head= 0;
463 assert(sendq_head < SENDQ_NR);
464 dep->de_sendq_head= sendq_head;
465
466 dep->de_flags |= DEF_PACK_SEND;
467
468 /* If the interrupt handler called, don't send a reply. The reply
469 * will be sent after all interrupts are handled.
470 */
471 if (from_int)
472 return;
473 reply(dep, OK, FALSE);
474
475 assert(dep->de_mode == DEM_ENABLED);
476 assert(dep->de_flags & DEF_ENABLED);
477}
478
479/*===========================================================================*
480 * do_vread *
481 *===========================================================================*/
482static void do_vread(mp, vectored)
483message *mp;
484int vectored;
485{
486 int port, count;
487 int size;
488 dpeth_t *dep;
489
490 port = mp->DL_PORT;
491 count = mp->DL_COUNT;
492 if (port < 0 || port >= DE_PORT_NR)
493 panic("", "dp8390: illegal port", port);
494 dep= &de_table[port];
495 dep->de_client= mp->DL_PROC;
496 if (dep->de_mode == DEM_SINK)
497 {
498 reply(dep, OK, FALSE);
499 return;
500 }
501 assert(dep->de_mode == DEM_ENABLED);
502 assert(dep->de_flags & DEF_ENABLED);
503
504 if(dep->de_flags & DEF_READING)
505 panic("", "dp8390: read already in progress", NO_NUM);
506
507 if (vectored)
508 {
509 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
510 (count > IOVEC_NR ? IOVEC_NR : count) *
511 sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
512 dep->de_read_iovec.iod_iovec_s = count;
513 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
514 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
515
516 dep->de_tmp_iovec = dep->de_read_iovec;
517 size= calc_iovec_size(&dep->de_tmp_iovec);
518 }
519 else
520 {
521 dep->de_read_iovec.iod_iovec[0].iov_addr =
522 (vir_bytes) mp->DL_ADDR;
523 dep->de_read_iovec.iod_iovec[0].iov_size =
524 mp->DL_COUNT;
525 dep->de_read_iovec.iod_iovec_s = 1;
526 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
527 dep->de_read_iovec.iod_iovec_addr = 0;
528 size= count;
529 }
530 if (size < ETH_MAX_PACK_SIZE_TAGGED)
531 panic("", "dp8390: wrong packet size", size);
532 dep->de_flags |= DEF_READING;
533
534 dp_recv(dep);
535
536 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
537 (DEF_READING|DEF_STOPPED))
538 {
539 /* The chip is stopped, and all arrived packets are
540 * delivered.
541 */
542 dp_reset(dep);
543 }
544 reply(dep, OK, FALSE);
545}
546
547/*===========================================================================*
548 * do_init *
549 *===========================================================================*/
550static void do_init(mp)
551message *mp;
552{
553 int port;
554 dpeth_t *dep;
555 message reply_mess;
556
557#if ENABLE_PCI
558 pci_conf(); /* Configure PCI devices. */
559#endif
560
561 port = mp->DL_PORT;
562 if (port < 0 || port >= DE_PORT_NR)
563 {
564 reply_mess.m_type= DL_INIT_REPLY;
565 reply_mess.m3_i1= ENXIO;
566 mess_reply(mp, &reply_mess);
567 return;
568 }
569 dep= &de_table[port];
570 if (dep->de_mode == DEM_DISABLED)
571 {
572 /* This is the default, try to (re)locate the device. */
573 conf_hw(dep);
574 if (dep->de_mode == DEM_DISABLED)
575 {
576 /* Probe failed, or the device is configured off. */
577 reply_mess.m_type= DL_INIT_REPLY;
578 reply_mess.m3_i1= ENXIO;
579 mess_reply(mp, &reply_mess);
580 return;
581 }
582 if (dep->de_mode == DEM_ENABLED)
583 dp_init(dep);
584 }
585
586 if (dep->de_mode == DEM_SINK)
587 {
588 strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
589 dep->de_address.ea_addr[5] = port;
590 dp_confaddr(dep);
591 reply_mess.m_type = DL_INIT_REPLY;
592 reply_mess.m3_i1 = mp->DL_PORT;
593 reply_mess.m3_i2 = DE_PORT_NR;
594 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
595 mess_reply(mp, &reply_mess);
596 return;
597 }
598 assert(dep->de_mode == DEM_ENABLED);
599 assert(dep->de_flags & DEF_ENABLED);
600
601 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
602
603 if (mp->DL_MODE & DL_PROMISC_REQ)
604 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
605 if (mp->DL_MODE & DL_MULTI_REQ)
606 dep->de_flags |= DEF_MULTI;
607 if (mp->DL_MODE & DL_BROAD_REQ)
608 dep->de_flags |= DEF_BROAD;
609
610 dep->de_client = mp->m_source;
611 dp_reinit(dep);
612
613 reply_mess.m_type = DL_INIT_REPLY;
614 reply_mess.m3_i1 = mp->DL_PORT;
615 reply_mess.m3_i2 = DE_PORT_NR;
616 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
617
618 mess_reply(mp, &reply_mess);
619}
620
621/*===========================================================================*
622 * do_int *
623 *===========================================================================*/
624static void do_int(dep)
625dpeth_t *dep;
626{
627 if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
628 reply(dep, OK, TRUE);
629}
630
631/*===========================================================================*
632 * do_getstat *
633 *===========================================================================*/
634static void do_getstat(mp)
635message *mp;
636{
637 int port;
638 dpeth_t *dep;
639
640 port = mp->DL_PORT;
641 if (port < 0 || port >= DE_PORT_NR)
642 panic("", "dp8390: illegal port", port);
643 dep= &de_table[port];
644 dep->de_client= mp->DL_PROC;
645 if (dep->de_mode == DEM_SINK)
646 {
647 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
648 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
649 reply(dep, OK, FALSE);
650 return;
651 }
652 assert(dep->de_mode == DEM_ENABLED);
653 assert(dep->de_flags & DEF_ENABLED);
654
655 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
656 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
657 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
658
659 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
660 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
661 reply(dep, OK, FALSE);
662}
663
664/*===========================================================================*
665 * do_getname *
666 *===========================================================================*/
667static void do_getname(mp)
668message *mp;
669{
670 int r;
671
672 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
673 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
674 mp->m_type= DL_NAME_REPLY;
675 r= send(mp->m_source, mp);
676 if (r != OK)
677 panic("dp8390", "do_getname: send failed: %d\n", r);
678}
679
680/*===========================================================================*
681 * do_stop *
682 *===========================================================================*/
683static void do_stop(mp)
684message *mp;
685{
686 int port;
687 dpeth_t *dep;
688
689 port = mp->DL_PORT;
690
691 if (port < 0 || port >= DE_PORT_NR)
692 panic("", "dp8390: illegal port", port);
693 dep= &de_table[port];
694 if (dep->de_mode == DEM_SINK)
695 return;
696 assert(dep->de_mode == DEM_ENABLED);
697
698 if (!(dep->de_flags & DEF_ENABLED))
699 return;
700
701 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
702 (dep->de_stopf)(dep);
703
704 dep->de_flags= DEF_EMPTY;
705}
706
707/*===========================================================================*
708 * dp_init *
709 *===========================================================================*/
710static void dp_init(dep)
711dpeth_t *dep;
712{
713 int dp_rcr_reg;
714 int i, r;
715
716 /* General initialization */
717 dep->de_flags = DEF_EMPTY;
718 (*dep->de_initf)(dep);
719
720 dp_confaddr(dep);
721
722 if (debug)
723 {
724 printf("%s: Ethernet address ", dep->de_name);
725 for (i= 0; i < 6; i++)
726 printf("%x%c", dep->de_address.ea_addr[i],
727 i < 5 ? ':' : '\n');
728 }
729
730 /* Initialization of the dp8390 following the mandatory procedure
731 * in reference manual ("DP8390D/NS32490D NIC Network Interface
732 * Controller", National Semiconductor, July 1995, Page 29).
733 */
734 /* Step 1: */
735 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
736 /* Step 2: */
737 if (dep->de_16bit)
738 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
739 else
740 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
741 /* Step 3: */
742 outb_reg0(dep, DP_RBCR0, 0);
743 outb_reg0(dep, DP_RBCR1, 0);
744 /* Step 4: */
745 dp_rcr_reg = 0;
746 if (dep->de_flags & DEF_PROMISC)
747 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
748 if (dep->de_flags & DEF_BROAD)
749 dp_rcr_reg |= RCR_AB;
750 if (dep->de_flags & DEF_MULTI)
751 dp_rcr_reg |= RCR_AM;
752 outb_reg0(dep, DP_RCR, dp_rcr_reg);
753 /* Step 5: */
754 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
755 /* Step 6: */
756 outb_reg0(dep, DP_BNRY, dep->de_startpage);
757 outb_reg0(dep, DP_PSTART, dep->de_startpage);
758 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
759 /* Step 7: */
760 outb_reg0(dep, DP_ISR, 0xFF);
761 /* Step 8: */
762 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
763 IMR_OVWE | IMR_CNTE);
764 /* Step 9: */
765 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
766
767 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
768 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
769 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
770 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
771 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
772 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
773
774 outb_reg1(dep, DP_MAR0, 0xff);
775 outb_reg1(dep, DP_MAR1, 0xff);
776 outb_reg1(dep, DP_MAR2, 0xff);
777 outb_reg1(dep, DP_MAR3, 0xff);
778 outb_reg1(dep, DP_MAR4, 0xff);
779 outb_reg1(dep, DP_MAR5, 0xff);
780 outb_reg1(dep, DP_MAR6, 0xff);
781 outb_reg1(dep, DP_MAR7, 0xff);
782
783 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
784 /* Step 10: */
785 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
786 /* Step 11: */
787 outb_reg0(dep, DP_TCR, TCR_NORMAL);
788
789 inb_reg0(dep, DP_CNTR0); /* reset counters by reading */
790 inb_reg0(dep, DP_CNTR1);
791 inb_reg0(dep, DP_CNTR2);
792
793 /* Finish the initialization. */
794 dep->de_flags |= DEF_ENABLED;
795 for (i= 0; i<dep->de_sendq_nr; i++)
796 dep->de_sendq[i].sq_filled= 0;
797 dep->de_sendq_head= 0;
798 dep->de_sendq_tail= 0;
799 if (!dep->de_prog_IO)
800 {
801 dep->de_user2nicf= dp_user2nic;
802 dep->de_nic2userf= dp_nic2user;
803 dep->de_getblockf= dp_getblock;
804 }
805 else if (dep->de_16bit)
806 {
807 dep->de_user2nicf= dp_pio16_user2nic;
808 dep->de_nic2userf= dp_pio16_nic2user;
809 dep->de_getblockf= dp_pio16_getblock;
810 }
811 else
812 {
813 dep->de_user2nicf= dp_pio8_user2nic;
814 dep->de_nic2userf= dp_pio8_nic2user;
815 dep->de_getblockf= dp_pio8_getblock;
816 }
817
818 /* Set the interrupt handler and policy. Do not automatically
819 * reenable interrupts. Return the IRQ line number on interrupts.
820 */
821 dep->de_hook = dep->de_irq;
822 r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
823 if (r != OK)
824 panic("DP8390", "sys_irqsetpolicy failed", r);
825
826 r= sys_irqenable(&dep->de_hook);
827 if (r != OK)
828 {
829 panic("DP8390", "unable enable interrupts", r);
830 }
831}
832
833/*===========================================================================*
834 * dp_confaddr *
835 *===========================================================================*/
836static void dp_confaddr(dep)
837dpeth_t *dep;
838{
839 int i;
840 char eakey[16];
841 static char eafmt[]= "x:x:x:x:x:x";
842 long v;
843
844 /* User defined ethernet address? */
845 strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
846 strcat(eakey, "_EA");
847
848 for (i= 0; i < 6; i++)
849 {
850 v= dep->de_address.ea_addr[i];
851 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
852 {
853 break;
854 }
855 dep->de_address.ea_addr[i]= v;
856 }
857
858 if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
859}
860
861/*===========================================================================*
862 * dp_reinit *
863 *===========================================================================*/
864static void dp_reinit(dep)
865dpeth_t *dep;
866{
867 int dp_rcr_reg;
868
869 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
870
871 dp_rcr_reg = 0;
872 if (dep->de_flags & DEF_PROMISC)
873 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
874 if (dep->de_flags & DEF_BROAD)
875 dp_rcr_reg |= RCR_AB;
876 if (dep->de_flags & DEF_MULTI)
877 dp_rcr_reg |= RCR_AM;
878 outb_reg0(dep, DP_RCR, dp_rcr_reg);
879}
880
881/*===========================================================================*
882 * dp_reset *
883 *===========================================================================*/
884static void dp_reset(dep)
885dpeth_t *dep;
886{
887 int i;
888
889 /* Stop chip */
890 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
891 outb_reg0(dep, DP_RBCR0, 0);
892 outb_reg0(dep, DP_RBCR1, 0);
893 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
894 ; /* Do nothing */
895 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
896 outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
897 outb_reg0(dep, DP_TCR, TCR_NORMAL);
898
899 /* Acknowledge the ISR_RDC (remote dma) interrupt. */
900 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
901 ; /* Do nothing */
902 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
903
904 /* Reset the transmit ring. If we were transmitting a packet, we
905 * pretend that the packet is processed. Higher layers will
906 * retransmit if the packet wasn't actually sent.
907 */
908 dep->de_sendq_head= dep->de_sendq_tail= 0;
909 for (i= 0; i<dep->de_sendq_nr; i++)
910 dep->de_sendq[i].sq_filled= 0;
911 dp_send(dep);
912 dep->de_flags &= ~DEF_STOPPED;
913}
914
915/*===========================================================================*
916 * dp_check_ints *
917 *===========================================================================*/
918static void dp_check_ints(dep)
919dpeth_t *dep;
920{
921 int isr, tsr;
922 int size, sendq_tail;
923
924 if (!(dep->de_flags & DEF_ENABLED))
925 panic("", "dp8390: got premature interrupt", NO_NUM);
926
927 for(;;)
928 {
929 isr = inb_reg0(dep, DP_ISR);
930 if (!isr)
931 break;
932 outb_reg0(dep, DP_ISR, isr);
933 if (isr & (ISR_PTX|ISR_TXE))
934 {
935 if (isr & ISR_TXE)
936 {
937#if DEBUG
938 { printf("%s: got send Error\n", dep->de_name); }
939#endif
940 dep->de_stat.ets_sendErr++;
941 }
942 else
943 {
944 tsr = inb_reg0(dep, DP_TSR);
945
946 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
947#if 0 /* Reserved in later manuals, should be ignored */
948 if (!(tsr & TSR_DFR))
949 {
950 /* In most (all?) implementations of
951 * the dp8390, this bit is set
952 * when the packet is not deferred
953 */
954 dep->de_stat.ets_transDef++;
955 }
956#endif
957 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
958 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
959 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
960 if (tsr & TSR_FU
961 && ++dep->de_stat.ets_fifoUnder <= 10)
962 {
963 printf("%s: fifo underrun\n",
964 dep->de_name);
965 }
966 if (tsr & TSR_CDH
967 && ++dep->de_stat.ets_CDheartbeat <= 10)
968 {
969 printf("%s: CD heart beat failure\n",
970 dep->de_name);
971 }
972 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
973 }
974 sendq_tail= dep->de_sendq_tail;
975
976 if (!(dep->de_sendq[sendq_tail].sq_filled))
977 {
978 /* Software bug? */
979 assert(!debug);
980
981 /* Or hardware bug? */
982 printf(
983 "%s: transmit interrupt, but not sending\n",
984 dep->de_name);
985 continue;
986 }
987 dep->de_sendq[sendq_tail].sq_filled= 0;
988 if (++sendq_tail == dep->de_sendq_nr)
989 sendq_tail= 0;
990 dep->de_sendq_tail= sendq_tail;
991 if (dep->de_sendq[sendq_tail].sq_filled)
992 {
993 size= dep->de_sendq[sendq_tail].sq_size;
994 outb_reg0(dep, DP_TPSR,
995 dep->de_sendq[sendq_tail].sq_sendpage);
996 outb_reg0(dep, DP_TBCR1, size >> 8);
997 outb_reg0(dep, DP_TBCR0, size & 0xff);
998 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
999 }
1000 if (dep->de_flags & DEF_SEND_AVAIL)
1001 dp_send(dep);
1002 }
1003
1004 if (isr & ISR_PRX)
1005 {
1006 /* Only call dp_recv if there is a read request */
1007 if (dep->de_flags & DEF_READING)
1008 dp_recv(dep);
1009 }
1010
1011 if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
1012 if (isr & ISR_CNT)
1013 {
1014 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
1015 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
1016 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
1017 }
1018 if (isr & ISR_OVW)
1019 {
1020 dep->de_stat.ets_OVW++;
1021#if 0
1022 { printW(); printf(
1023 "%s: got overwrite warning\n", dep->de_name); }
1024#endif
1025 if (dep->de_flags & DEF_READING)
1026 {
1027 printf(
1028"dp_check_ints: strange: overwrite warning and pending read request\n");
1029 dp_recv(dep);
1030 }
1031 }
1032 if (isr & ISR_RDC)
1033 {
1034 /* Nothing to do */
1035 }
1036 if (isr & ISR_RST)
1037 {
1038 /* this means we got an interrupt but the ethernet
1039 * chip is shutdown. We set the flag DEF_STOPPED,
1040 * and continue processing arrived packets. When the
1041 * receive buffer is empty, we reset the dp8390.
1042 */
1043#if 0
1044 { printW(); printf(
1045 "%s: NIC stopped\n", dep->de_name); }
1046#endif
1047 dep->de_flags |= DEF_STOPPED;
1048 break;
1049 }
1050 }
1051 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
1052 (DEF_READING|DEF_STOPPED))
1053 {
1054 /* The chip is stopped, and all arrived packets are
1055 * delivered.
1056 */
1057 dp_reset(dep);
1058 }
1059}
1060
1061/*===========================================================================*
1062 * dp_recv *
1063 *===========================================================================*/
1064static void dp_recv(dep)
1065dpeth_t *dep;
1066{
1067 dp_rcvhdr_t header;
1068 unsigned pageno, curr, next;
1069 vir_bytes length;
1070 int packet_processed, r;
1071 u16_t eth_type;
1072
1073 packet_processed = FALSE;
1074 pageno = inb_reg0(dep, DP_BNRY) + 1;
1075 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
1076
1077 do
1078 {
1079 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
1080 curr = inb_reg1(dep, DP_CURR);
1081 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
1082
1083 if (curr == pageno) break;
1084
1085 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
1086 &header);
1087 (dep->de_getblockf)(dep, pageno, sizeof(header) +
1088 2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
1089
1090 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
1091 sizeof(dp_rcvhdr_t);
1092 next = header.dr_next;
1093 if (length < ETH_MIN_PACK_SIZE ||
1094 length > ETH_MAX_PACK_SIZE_TAGGED)
1095 {
1096 printf("%s: packet with strange length arrived: %d\n",
1097 dep->de_name, (int) length);
1098 next= curr;
1099 }
1100 else if (next < dep->de_startpage || next >= dep->de_stoppage)
1101 {
1102 printf("%s: strange next page\n", dep->de_name);
1103 next= curr;
1104 }
1105 else if (eth_type == eth_ign_proto)
1106 {
1107 /* Hack: ignore packets of a given protocol, useful
1108 * if you share a net with 80 computers sending
1109 * Amoeba FLIP broadcasts. (Protocol 0x8146.)
1110 */
1111 static int first= 1;
1112 if (first)
1113 {
1114 first= 0;
1115 printf("%s: dropping proto 0x%04x packets\n",
1116 dep->de_name,
1117 ntohs(eth_ign_proto));
1118 }
1119 dep->de_stat.ets_packetR++;
1120 }
1121 else if (header.dr_status & RSR_FO)
1122 {
1123 /* This is very serious, so we issue a warning and
1124 * reset the buffers */
1125 printf("%s: fifo overrun, resetting receive buffer\n",
1126 dep->de_name);
1127 dep->de_stat.ets_fifoOver++;
1128 next = curr;
1129 }
1130 else if ((header.dr_status & RSR_PRX) &&
1131 (dep->de_flags & DEF_ENABLED))
1132 {
1133 r = dp_pkt2user(dep, pageno, length);
1134 if (r != OK)
1135 return;
1136
1137 packet_processed = TRUE;
1138 dep->de_stat.ets_packetR++;
1139 }
1140 if (next == dep->de_startpage)
1141 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
1142 else
1143 outb_reg0(dep, DP_BNRY, next - 1);
1144
1145 pageno = next;
1146 }
1147 while (!packet_processed);
1148}
1149
1150/*===========================================================================*
1151 * dp_send *
1152 *===========================================================================*/
1153static void dp_send(dep)
1154dpeth_t *dep;
1155{
1156 if (!(dep->de_flags & DEF_SEND_AVAIL))
1157 return;
1158
1159 dep->de_flags &= ~DEF_SEND_AVAIL;
1160 switch(dep->de_sendmsg.m_type)
1161 {
1162 case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
1163 case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
1164 default:
1165 panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
1166 break;
1167 }
1168}
1169
1170/*===========================================================================*
1171 * dp_getblock *
1172 *===========================================================================*/
1173static void dp_getblock(dep, page, offset, size, dst)
1174dpeth_t *dep;
1175int page;
1176size_t offset;
1177size_t size;
1178void *dst;
1179{
1180 int r;
1181
1182 offset = page * DP_PAGESIZE + offset;
1183
1184 r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,
1185 SELF, D, (vir_bytes)dst, size);
1186
1187 if (r != OK)
1188 panic("DP8390", "dp_getblock: sys_vircopy failed", r);
1189}
1190
1191/*===========================================================================*
1192 * dp_pio8_getblock *
1193 *===========================================================================*/
1194static void dp_pio8_getblock(dep, page, offset, size, dst)
1195dpeth_t *dep;
1196int page;
1197size_t offset;
1198size_t size;
1199void *dst;
1200{
1201 offset = page * DP_PAGESIZE + offset;
1202 outb_reg0(dep, DP_RBCR0, size & 0xFF);
1203 outb_reg0(dep, DP_RBCR1, size >> 8);
1204 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
1205 outb_reg0(dep, DP_RSAR1, offset >> 8);
1206 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1207
1208 insb(dep->de_data_port, dst, size);
1209}
1210
1211/*===========================================================================*
1212 * dp_pio16_getblock *
1213 *===========================================================================*/
1214static void dp_pio16_getblock(dep, page, offset, size, dst)
1215dpeth_t *dep;
1216int page;
1217size_t offset;
1218size_t size;
1219void *dst;
1220{
1221 offset = page * DP_PAGESIZE + offset;
1222 outb_reg0(dep, DP_RBCR0, size & 0xFF);
1223 outb_reg0(dep, DP_RBCR1, size >> 8);
1224 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
1225 outb_reg0(dep, DP_RSAR1, offset >> 8);
1226 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1227
1228 assert (!(size & 1));
1229 insw(dep->de_data_port, dst, size);
1230}
1231
1232/*===========================================================================*
1233 * dp_pkt2user *
1234 *===========================================================================*/
1235static int dp_pkt2user(dep, page, length)
1236dpeth_t *dep;
1237int page, length;
1238{
1239 int last, count;
1240
1241 if (!(dep->de_flags & DEF_READING))
1242 return EGENERIC;
1243
1244 last = page + (length - 1) / DP_PAGESIZE;
1245 if (last >= dep->de_stoppage)
1246 {
1247 count = (dep->de_stoppage - page) * DP_PAGESIZE -
1248 sizeof(dp_rcvhdr_t);
1249
1250 /* Save read_iovec since we need it twice. */
1251 dep->de_tmp_iovec = dep->de_read_iovec;
1252 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1253 sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
1254 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
1255 &dep->de_read_iovec, count, length - count);
1256 }
1257 else
1258 {
1259 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1260 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
1261 }
1262
1263 dep->de_read_s = length;
1264 dep->de_flags |= DEF_PACK_RECV;
1265 dep->de_flags &= ~DEF_READING;
1266
1267 return OK;
1268}
1269
1270/*===========================================================================*
1271 * dp_user2nic *
1272 *===========================================================================*/
1273static void dp_user2nic(dep, iovp, offset, nic_addr, count)
1274dpeth_t *dep;
1275iovec_dat_t *iovp;
1276vir_bytes offset;
1277int nic_addr;
1278vir_bytes count;
1279{
1280 vir_bytes vir_hw, vir_user;
1281 int bytes, i, r;
1282
1283 vir_hw = dep->de_linmem + nic_addr;
1284
1285 i= 0;
1286 while (count > 0)
1287 {
1288 if (i >= IOVEC_NR)
1289 {
1290 dp_next_iovec(iovp);
1291 i= 0;
1292 continue;
1293 }
1294 assert(i < iovp->iod_iovec_s);
1295 if (offset >= iovp->iod_iovec[i].iov_size)
1296 {
1297 offset -= iovp->iod_iovec[i].iov_size;
1298 i++;
1299 continue;
1300 }
1301 bytes = iovp->iod_iovec[i].iov_size - offset;
1302 if (bytes > count)
1303 bytes = count;
1304
1305 r= sys_vircopy(iovp->iod_proc_nr, D,
1306 iovp->iod_iovec[i].iov_addr + offset,
1307 SELF, BIOS_SEG, vir_hw, bytes);
1308 if (r != OK)
1309 panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
1310
1311 count -= bytes;
1312 vir_hw += bytes;
1313 offset += bytes;
1314 }
1315 assert(count == 0);
1316}
1317
1318/*===========================================================================*
1319 * dp_pio8_user2nic *
1320 *===========================================================================*/
1321static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
1322dpeth_t *dep;
1323iovec_dat_t *iovp;
1324vir_bytes offset;
1325int nic_addr;
1326vir_bytes count;
1327{
1328 phys_bytes phys_user;
1329 int bytes, i;
1330
1331 outb_reg0(dep, DP_ISR, ISR_RDC);
1332
1333 outb_reg0(dep, DP_RBCR0, count & 0xFF);
1334 outb_reg0(dep, DP_RBCR1, count >> 8);
1335 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1336 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1337 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1338
1339 i= 0;
1340 while (count > 0)
1341 {
1342 if (i >= IOVEC_NR)
1343 {
1344 dp_next_iovec(iovp);
1345 i= 0;
1346 continue;
1347 }
1348 assert(i < iovp->iod_iovec_s);
1349 if (offset >= iovp->iod_iovec[i].iov_size)
1350 {
1351 offset -= iovp->iod_iovec[i].iov_size;
1352 i++;
1353 continue;
1354 }
1355 bytes = iovp->iod_iovec[i].iov_size - offset;
1356 if (bytes > count)
1357 bytes = count;
1358
1359 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
1360 iovp->iod_iovec[i].iov_addr + offset, bytes);
1361 count -= bytes;
1362 offset += bytes;
1363 }
1364 assert(count == 0);
1365
1366 for (i= 0; i<100; i++)
1367 {
1368 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1369 break;
1370 }
1371 if (i == 100)
1372 {
1373 panic("", "dp8390: remote dma failed to complete", NO_NUM);
1374 }
1375}
1376
1377/*===========================================================================*
1378 * dp_pio16_user2nic *
1379 *===========================================================================*/
1380static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
1381dpeth_t *dep;
1382iovec_dat_t *iovp;
1383vir_bytes offset;
1384int nic_addr;
1385vir_bytes count;
1386{
1387 vir_bytes vir_user;
1388 vir_bytes ecount;
1389 int i, r, bytes, user_proc;
1390 u8_t two_bytes[2];
1391 int odd_byte;
1392
1393 ecount= (count+1) & ~1;
1394 odd_byte= 0;
1395
1396 outb_reg0(dep, DP_ISR, ISR_RDC);
1397 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1398 outb_reg0(dep, DP_RBCR1, ecount >> 8);
1399 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1400 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1401 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1402
1403 i= 0;
1404 while (count > 0)
1405 {
1406 if (i >= IOVEC_NR)
1407 {
1408 dp_next_iovec(iovp);
1409 i= 0;
1410 continue;
1411 }
1412 assert(i < iovp->iod_iovec_s);
1413 if (offset >= iovp->iod_iovec[i].iov_size)
1414 {
1415 offset -= iovp->iod_iovec[i].iov_size;
1416 i++;
1417 continue;
1418 }
1419 bytes = iovp->iod_iovec[i].iov_size - offset;
1420 if (bytes > count)
1421 bytes = count;
1422
1423 user_proc= iovp->iod_proc_nr;
1424 vir_user= iovp->iod_iovec[i].iov_addr + offset;
1425 if (odd_byte)
1426 {
1427 r= sys_vircopy(user_proc, D, vir_user,
1428 SELF, D, (vir_bytes)&two_bytes[1], 1);
1429 if (r != OK)
1430 {
1431 panic("DP8390",
1432 "dp_pio16_user2nic: sys_vircopy failed",
1433 r);
1434 }
1435 outw(dep->de_data_port, *(u16_t *)two_bytes);
1436 count--;
1437 offset++;
1438 bytes--;
1439 vir_user++;
1440 odd_byte= 0;
1441 if (!bytes)
1442 continue;
1443 }
1444 ecount= bytes & ~1;
1445 if (ecount != 0)
1446 {
1447 do_vir_outsw(dep->de_data_port, user_proc, vir_user,
1448 ecount);
1449 count -= ecount;
1450 offset += ecount;
1451 bytes -= ecount;
1452 vir_user += ecount;
1453 }
1454 if (bytes)
1455 {
1456 assert(bytes == 1);
1457 r= sys_vircopy(user_proc, D, vir_user,
1458 SELF, D, (vir_bytes)&two_bytes[0], 1);
1459 if (r != OK)
1460 {
1461 panic("DP8390",
1462 "dp_pio16_user2nic: sys_vircopy failed",
1463 r);
1464 }
1465 count--;
1466 offset++;
1467 bytes--;
1468 vir_user++;
1469 odd_byte= 1;
1470 }
1471 }
1472 assert(count == 0);
1473
1474 if (odd_byte)
1475 outw(dep->de_data_port, *(u16_t *)two_bytes);
1476
1477 for (i= 0; i<100; i++)
1478 {
1479 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1480 break;
1481 }
1482 if (i == 100)
1483 {
1484 panic("", "dp8390: remote dma failed to complete", NO_NUM);
1485 }
1486}
1487
1488/*===========================================================================*
1489 * dp_nic2user *
1490 *===========================================================================*/
1491static void dp_nic2user(dep, nic_addr, iovp, offset, count)
1492dpeth_t *dep;
1493int nic_addr;
1494iovec_dat_t *iovp;
1495vir_bytes offset;
1496vir_bytes count;
1497{
1498 vir_bytes vir_hw, vir_user;
1499 int bytes, i, r;
1500
1501 vir_hw = dep->de_linmem + nic_addr;
1502
1503 i= 0;
1504 while (count > 0)
1505 {
1506 if (i >= IOVEC_NR)
1507 {
1508 dp_next_iovec(iovp);
1509 i= 0;
1510 continue;
1511 }
1512 assert(i < iovp->iod_iovec_s);
1513 if (offset >= iovp->iod_iovec[i].iov_size)
1514 {
1515 offset -= iovp->iod_iovec[i].iov_size;
1516 i++;
1517 continue;
1518 }
1519 bytes = iovp->iod_iovec[i].iov_size - offset;
1520 if (bytes > count)
1521 bytes = count;
1522
1523 r= sys_vircopy(SELF, BIOS_SEG, vir_hw,
1524 iovp->iod_proc_nr, D,
1525 iovp->iod_iovec[i].iov_addr + offset, bytes);
1526 if (r != OK)
1527 panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
1528
1529 count -= bytes;
1530 vir_hw += bytes;
1531 offset += bytes;
1532 }
1533 assert(count == 0);
1534}
1535
1536/*===========================================================================*
1537 * dp_pio8_nic2user *
1538 *===========================================================================*/
1539static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
1540dpeth_t *dep;
1541int nic_addr;
1542iovec_dat_t *iovp;
1543vir_bytes offset;
1544vir_bytes count;
1545{
1546 phys_bytes phys_user;
1547 int bytes, i;
1548
1549 outb_reg0(dep, DP_RBCR0, count & 0xFF);
1550 outb_reg0(dep, DP_RBCR1, count >> 8);
1551 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1552 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1553 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1554
1555 i= 0;
1556 while (count > 0)
1557 {
1558 if (i >= IOVEC_NR)
1559 {
1560 dp_next_iovec(iovp);
1561 i= 0;
1562 continue;
1563 }
1564 assert(i < iovp->iod_iovec_s);
1565 if (offset >= iovp->iod_iovec[i].iov_size)
1566 {
1567 offset -= iovp->iod_iovec[i].iov_size;
1568 i++;
1569 continue;
1570 }
1571 bytes = iovp->iod_iovec[i].iov_size - offset;
1572 if (bytes > count)
1573 bytes = count;
1574
1575 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
1576 iovp->iod_iovec[i].iov_addr + offset, bytes);
1577 count -= bytes;
1578 offset += bytes;
1579 }
1580 assert(count == 0);
1581}
1582
1583/*===========================================================================*
1584 * dp_pio16_nic2user *
1585 *===========================================================================*/
1586static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
1587dpeth_t *dep;
1588int nic_addr;
1589iovec_dat_t *iovp;
1590vir_bytes offset;
1591vir_bytes count;
1592{
1593 vir_bytes vir_user;
1594 vir_bytes ecount;
1595 int i, r, bytes, user_proc;
1596 u8_t two_bytes[2];
1597 int odd_byte;
1598
1599 ecount= (count+1) & ~1;
1600 odd_byte= 0;
1601
1602 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1603 outb_reg0(dep, DP_RBCR1, ecount >> 8);
1604 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1605 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1606 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1607
1608 i= 0;
1609 while (count > 0)
1610 {
1611 if (i >= IOVEC_NR)
1612 {
1613 dp_next_iovec(iovp);
1614 i= 0;
1615 continue;
1616 }
1617 assert(i < iovp->iod_iovec_s);
1618 if (offset >= iovp->iod_iovec[i].iov_size)
1619 {
1620 offset -= iovp->iod_iovec[i].iov_size;
1621 i++;
1622 continue;
1623 }
1624 bytes = iovp->iod_iovec[i].iov_size - offset;
1625 if (bytes > count)
1626 bytes = count;
1627
1628 user_proc= iovp->iod_proc_nr;
1629 vir_user= iovp->iod_iovec[i].iov_addr + offset;
1630 if (odd_byte)
1631 {
1632 r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
1633 user_proc, D, vir_user, 1);
1634 if (r != OK)
1635 {
1636 panic("DP8390",
1637 "dp_pio16_nic2user: sys_vircopy failed",
1638 r);
1639 }
1640 count--;
1641 offset++;
1642 bytes--;
1643 vir_user++;
1644 odd_byte= 0;
1645 if (!bytes)
1646 continue;
1647 }
1648 ecount= bytes & ~1;
1649 if (ecount != 0)
1650 {
1651 do_vir_insw(dep->de_data_port, user_proc, vir_user,
1652 ecount);
1653 count -= ecount;
1654 offset += ecount;
1655 bytes -= ecount;
1656 vir_user += ecount;
1657 }
1658 if (bytes)
1659 {
1660 assert(bytes == 1);
1661 *(u16_t *)two_bytes= inw(dep->de_data_port);
1662 r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
1663 user_proc, D, vir_user, 1);
1664 if (r != OK)
1665 {
1666 panic("DP8390",
1667 "dp_pio16_nic2user: sys_vircopy failed",
1668 r);
1669 }
1670 count--;
1671 offset++;
1672 bytes--;
1673 vir_user++;
1674 odd_byte= 1;
1675 }
1676 }
1677 assert(count == 0);
1678}
1679
1680/*===========================================================================*
1681 * dp_next_iovec *
1682 *===========================================================================*/
1683static void dp_next_iovec(iovp)
1684iovec_dat_t *iovp;
1685{
1686 assert(iovp->iod_iovec_s > IOVEC_NR);
1687
1688 iovp->iod_iovec_s -= IOVEC_NR;
1689
1690 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1691
1692 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1693 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1694 sizeof(iovec_t), iovp->iod_iovec);
1695}
1696
1697/*===========================================================================*
1698 * conf_hw *
1699 *===========================================================================*/
1700static void conf_hw(dep)
1701dpeth_t *dep;
1702{
1703 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
1704
1705 int ifnr;
1706 dp_conf_t *dcp;
1707
1708 dep->de_mode= DEM_DISABLED; /* Superfluous */
1709 ifnr= dep-de_table;
1710
1711 dcp= &dp_conf[ifnr];
1712 update_conf(dep, dcp);
1713 if (dep->de_mode != DEM_ENABLED)
1714 return;
1715 if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
1716 {
1717 printf("%s: No ethernet card found at 0x%x\n",
1718 dep->de_name, dep->de_base_port);
1719 dep->de_mode= DEM_DISABLED;
1720 return;
1721 }
1722
1723/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
1724
1725 dep->de_flags = DEF_EMPTY;
1726 dep->de_stat = empty_stat;
1727}
1728
1729/*===========================================================================*
1730 * update_conf *
1731 *===========================================================================*/
1732static void update_conf(dep, dcp)
1733dpeth_t *dep;
1734dp_conf_t *dcp;
1735{
1736 long v;
1737 static char dpc_fmt[] = "x:d:x:x";
1738
1739#if ENABLE_PCI
1740 if (dep->de_pci)
1741 {
1742 if (dep->de_pci == 1)
1743 {
1744 /* PCI device is present */
1745 dep->de_mode= DEM_ENABLED;
1746 }
1747 return; /* Already configured */
1748 }
1749#endif
1750
1751 /* Get the default settings and modify them from the environment. */
1752 dep->de_mode= DEM_SINK;
1753 v= dcp->dpc_port;
1754 switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
1755 case EP_OFF:
1756 dep->de_mode= DEM_DISABLED;
1757 break;
1758 case EP_ON:
1759 case EP_SET:
1760 dep->de_mode= DEM_ENABLED; /* Might become disabled if
1761 * all probes fail */
1762 break;
1763 }
1764 dep->de_base_port= v;
1765
1766 v= dcp->dpc_irq | DEI_DEFAULT;
1767 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
1768 (long) NR_IRQ_VECTORS - 1);
1769 dep->de_irq= v;
1770
1771 v= dcp->dpc_mem;
1772 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
1773 dep->de_linmem= v;
1774
1775 v= 0;
1776 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
1777 dep->de_ramsize= v;
1778}
1779
1780/*===========================================================================*
1781 * calc_iovec_size *
1782 *===========================================================================*/
1783static int calc_iovec_size(iovp)
1784iovec_dat_t *iovp;
1785{
1786 /* Calculate the size of a request. Note that the iovec_dat
1787 * structure will be unusable after calc_iovec_size.
1788 */
1789 int size;
1790 int i;
1791
1792 size= 0;
1793 i= 0;
1794 while (i < iovp->iod_iovec_s)
1795 {
1796 if (i >= IOVEC_NR)
1797 {
1798 dp_next_iovec(iovp);
1799 i= 0;
1800 continue;
1801 }
1802 size += iovp->iod_iovec[i].iov_size;
1803 i++;
1804 }
1805 return size;
1806}
1807
1808/*===========================================================================*
1809 * reply *
1810 *===========================================================================*/
1811static void reply(dep, err, may_block)
1812dpeth_t *dep;
1813int err;
1814int may_block;
1815{
1816 message reply;
1817 int status;
1818 int r;
1819
1820 status = 0;
1821 if (dep->de_flags & DEF_PACK_SEND)
1822 status |= DL_PACK_SEND;
1823 if (dep->de_flags & DEF_PACK_RECV)
1824 status |= DL_PACK_RECV;
1825
1826 reply.m_type = DL_TASK_REPLY;
1827 reply.DL_PORT = dep - de_table;
1828 reply.DL_PROC = dep->de_client;
1829 reply.DL_STAT = status | ((u32_t) err << 16);
1830 reply.DL_COUNT = dep->de_read_s;
1831 reply.DL_CLCK = 0; /* Don't know */
1832 r= send(dep->de_client, &reply);
1833
1834 if (r == ELOCKED && may_block)
1835 {
1836#if 0
1837 printf("send locked\n");
1838#endif
1839 return;
1840 }
1841
1842 if (r < 0)
1843 panic("", "dp8390: send failed:", r);
1844
1845 dep->de_read_s = 0;
1846 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
1847}
1848
1849/*===========================================================================*
1850 * mess_reply *
1851 *===========================================================================*/
1852static void mess_reply(req, reply_mess)
1853message *req;
1854message *reply_mess;
1855{
1856 if (send(req->m_source, reply_mess) != OK)
1857 panic("", "dp8390: unable to mess_reply", NO_NUM);
1858}
1859
1860/*===========================================================================*
1861 * get_userdata *
1862 *===========================================================================*/
1863static void get_userdata(user_proc, user_addr, count, loc_addr)
1864int user_proc;
1865vir_bytes user_addr;
1866vir_bytes count;
1867void *loc_addr;
1868{
1869 int r;
1870
1871 r= sys_vircopy(user_proc, D, user_addr,
1872 SELF, D, (vir_bytes)loc_addr, count);
1873 if (r != OK)
1874 panic("DP8390", "get_userdata: sys_vircopy failed", r);
1875}
1876
1877/*===========================================================================*
1878 * put_userdata *
1879 *===========================================================================*/
1880static void put_userdata(user_proc, user_addr, count, loc_addr)
1881int user_proc;
1882vir_bytes user_addr;
1883vir_bytes count;
1884void *loc_addr;
1885{
1886 int r;
1887
1888 r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
1889 user_proc, D, user_addr, count);
1890 if (r != OK)
1891 panic("DP8390", "put_userdata: sys_vircopy failed", r);
1892}
1893
1894u8_t inb(port_t port)
1895{
1896 int r;
1897 u32_t value;
1898
1899 r= sys_inb(port, &value);
1900 if (r != OK)
1901 panic("DP8390","sys_inb failed", r);
1902 return value;
1903}
1904
1905u16_t inw(port_t port)
1906{
1907 int r;
1908 unsigned long value;
1909
1910 r= sys_inw(port, &value);
1911 if (r != OK)
1912 panic("DP8390", "sys_inw failed", r);
1913 return (u16_t) value;
1914}
1915
1916void outb(port_t port, u8_t value)
1917{
1918 int r;
1919
1920 r= sys_outb(port, value);
1921 if (r != OK)
1922 panic("DP8390", "sys_outb failed", r);
1923}
1924
1925void outw(port_t port, u16_t value)
1926{
1927 int r;
1928
1929 r= sys_outw(port, value);
1930 if (r != OK)
1931 panic("DP8390", "sys_outw failed", r);
1932}
1933
1934static void insb(port_t port, void *buf, size_t size)
1935{
1936 do_vir_insb(port, SELF, (vir_bytes)buf, size);
1937}
1938
1939static void insw(port_t port, void *buf, size_t size)
1940{
1941 do_vir_insw(port, SELF, (vir_bytes)buf, size);
1942}
1943
1944static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
1945{
1946 int r;
1947
1948 r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
1949 if (r != OK)
1950 panic("DP8390", "sys_sdevio failed", r);
1951}
1952
1953static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
1954{
1955 int r;
1956
1957 r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
1958 if (r != OK)
1959 panic("DP8390", "sys_sdevio failed", r);
1960}
1961
1962static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
1963{
1964 int r;
1965
1966 r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
1967 if (r != OK)
1968 panic("DP8390", "sys_sdevio failed", r);
1969}
1970
1971static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
1972{
1973 int r;
1974
1975 r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
1976 if (r != OK)
1977 panic("DP8390", "sys_sdevio failed", r);
1978}
1979
1980/*
1981 * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
1982 */
Note: See TracBrowser for help on using the repository browser.