1 /*
2 * lance.c
3 *
4 * This file contains a ethernet device driver for AMD LANCE 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_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK
31 * |------------|----------|---------|----------|---------|---------|
32 * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
33 * |------------|----------|---------|----------|---------|---------|
34 *
35 * m_type m3_i1 m3_i2 m3_ca1
36 * |------------+---------+-----------+---------------|
37 * |DL_INIT_REPL| port nr | last port | ethernet addr |
38 * |------------|---------|-----------|---------------|
39 *
40 * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
41 * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
42 */
43
44 #define VERBOSE 0
45
46 #include "../drivers.h"
47
48 #include <minix/keymap.h>
49 #include <net/hton.h>
50 #include <net/gen/ether.h>
51 #include <net/gen/eth_io.h>
52 #include <assert.h>
53
54 #include <minix/syslib.h>
55
56 #include "lance.h"
57 #include "../libpci/pci.h"
58 /*#include "proc.h"*/
59
60 #include <sys/ioc_memory.h>
61
62 /* new I/O functions in Minix 3 */
63 #define out_byte( x, y ) sys_outb( x, y )
64 #define out_word( x, y ) sys_outw( x, y )
65
66 static U8_t in_byte(U16_t port)
67 {
68 U8_t value;
69 int s;
70 if ((s=sys_inb(port, &value)) != OK)
71 printf( "lance: warning, sys_inb failed: %d\n", s );
72 return value;
73 }
74
75 static U16_t in_word( U16_t port)
76 {
77 U16_t value;
78 int s;
79 if ((s=sys_inw(port, &value)) != OK)
80 printf( "lance: warning, sys_inw failed: %d\n", s );
81 return value;
82 }
83 /*
84 #define in_byte( x ) inb( x )
85 #define in_word( x ) inw( x )
86 */
87
88 static ether_card_t ec_table[EC_PORT_NR_MAX];
89 static int eth_tasknr= ANY;
90 static u16_t eth_ign_proto;
91
92 /* Configuration */
93 typedef struct ec_conf
94 {
95 port_t ec_port;
96 int ec_irq;
97 phys_bytes ec_mem;
98 char *ec_envvar;
99 } ec_conf_t;
100
101 /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
102 ec_conf_t ec_conf[]= /* Card addresses */
103 {
104 /* I/O port, IRQ, Buffer address, Env. var, Buf selector. */
105 { 0x1000, 9, 0x00000, "LANCE0" },
106 { 0xD000, 15, 0x00000, "LANCE1" },
107 };
108
109 /* Actually, we use PCI-BIOS info. */
110 PRIVATE struct pcitab
111 {
112 u16_t vid;
113 u16_t did;
114 int checkclass;
115 } pcitab[]=
116 {
117 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 }, /* AMD LANCE */
118
119 { 0x0000, 0x0000, 0 }
120 };
121 /*
122 struct pci_device pci_dev_list[] = {
123 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
124 "AMD Lance/PCI", 0, 0, 0, 0, 0, 0},
125 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
126 "AMD Lance/PCI", 0, 0, 0, 0, 0, 0},
127 {0, 0, NULL, 0, 0, 0, 0, 0, 0}
128 };
129 */
130
131 /* General */
132 _PROTOTYPE( static void do_init, (message *mp) );
133 _PROTOTYPE( static void ec_init, (ether_card_t *ec) );
134 _PROTOTYPE( static void ec_confaddr, (ether_card_t *ec) );
135 _PROTOTYPE( static void ec_reinit, (ether_card_t *ec) );
136 _PROTOTYPE( static void ec_check_ints, (ether_card_t *ec) );
137 _PROTOTYPE( static void conf_hw, (ether_card_t *ec) );
138 /*_PROTOTYPE( static int ec_handler, (irq_hook_t *hook) );*/
139 _PROTOTYPE( static void update_conf, (ether_card_t *ec, ec_conf_t *ecp) );
140 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
141 _PROTOTYPE( static void do_int, (ether_card_t *ec) );
142 _PROTOTYPE( static void reply,
143 (ether_card_t *ec, int err, int may_block) );
144 _PROTOTYPE( static void ec_reset, (ether_card_t *ec) );
145 _PROTOTYPE( static void ec_send, (ether_card_t *ec) );
146 _PROTOTYPE( static void ec_recv, (ether_card_t *ec) );
147 _PROTOTYPE( static void do_vwrite,
148 (message *mp, int from_int, int vectored) );
149 _PROTOTYPE( static void do_vread, (message *mp, int vectored) );
150 _PROTOTYPE( static void get_userdata,
151 (int user_proc, vir_bytes user_addr,
152 vir_bytes count, void *loc_addr) );
153 _PROTOTYPE( static void ec_user2nic,
154 (ether_card_t *dep, iovec_dat_t *iovp,
155 vir_bytes offset, int nic_addr,
156 vir_bytes count) );
157 _PROTOTYPE( static void ec_nic2user,
158 (ether_card_t *ec, int nic_addr,
159 iovec_dat_t *iovp, vir_bytes offset,
160 vir_bytes count) );
161 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
162 _PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );
163 _PROTOTYPE( static void do_getstat, (message *mp) );
164 _PROTOTYPE( static void put_userdata,
165 (int user_proc,
166 vir_bytes user_addr, vir_bytes count,
167 void *loc_addr) );
168 _PROTOTYPE( static void do_stop, (message *mp) );
169 _PROTOTYPE( static void do_getname, (message *mp) );
170
171 _PROTOTYPE( static void lance_dump, (void) );
172 _PROTOTYPE( static void lance_stop, (void) );
173 _PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec) );
174
175 /* probe+init LANCE cards */
176 _PROTOTYPE( static int lance_probe, (ether_card_t *ec) );
177 _PROTOTYPE( static void lance_init_card, (ether_card_t *ec) );
178
179 /* --- LANCE --- */
180 /* General */
181 #define Address unsigned long
182
183
184 /* Minix 3 */
185 #define virt_to_bus(x) (vir2phys((unsigned long)x))
186 unsigned long vir2phys( unsigned long x )
187 {
188 int r;
189 unsigned long value;
190
191 if ( (r=sys_umap( SELF, D, x, 4, &value )) != OK )
192 panic( "lance", "sys_umap failed", r );
193
194 return value;
195 }
196
197 /* DMA limitations */
198 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
199
200 #define CORRECT_DMA_MEM() ( (virt_to_bus(lance + sizeof(lance)) & ~DMA_ADDR_MASK) == 0 )
201
202 #define ETH_FRAME_LEN 1518
203
204 #define LANCE_MUST_PAD 0x00000001
205 #define LANCE_ENABLE_AUTOSELECT 0x00000002
206 #define LANCE_SELECT_PHONELINE 0x00000004
207 #define LANCE_MUST_UNRESET 0x00000008
208
209 static const struct lance_chip_type
210 {
211 int id_number;
212 const char *name;
213 int flags;
214 } chip_table[] = {
215 {0x0000, "LANCE 7990", /* Ancient lance chip. */
216 LANCE_MUST_PAD + LANCE_MUST_UNRESET},
217 {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
218 LANCE_ENABLE_AUTOSELECT},
219 {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
220 LANCE_ENABLE_AUTOSELECT},
221 {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
222 LANCE_ENABLE_AUTOSELECT},
223 {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
224 LANCE_ENABLE_AUTOSELECT},
225 {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
226 LANCE_ENABLE_AUTOSELECT},
227 {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
228 LANCE_ENABLE_AUTOSELECT},
229 {0x2626, "PCnet/HomePNA 79C978",
230 LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
231 {0x0, "PCnet (unknown)",
232 LANCE_ENABLE_AUTOSELECT},
233 };
234
235 /* ############## for LANCE device ############## */
236 #define LANCE_ETH_ADDR 0x0
237 #define LANCE_DATA 0x10
238 #define LANCE_ADDR 0x12
239 #define LANCE_RESET 0x14
240 #define LANCE_BUS_IF 0x16
241 #define LANCE_TOTAL_SIZE 0x18
242
243 /* Use 2^4=16 {Rx,Tx} buffers */
244 #define LANCE_LOG_RX_BUFFERS 4
245 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
246 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
247 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
248
249 #define LANCE_LOG_TX_BUFFERS 4
250 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
251 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
252 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
253
254 /* for lance_interface */
255 struct lance_init_block
256 {
257 unsigned short mode;
258 unsigned char phys_addr[6];
259 unsigned long filter[2];
260 Address rx_ring;
261 Address tx_ring;
262 };
263
264 struct lance_rx_head
265 {
266 union {
267 Address base;
268 unsigned char addr[4];
269 } u;
270 short buf_length; /* 2s complement */
271 short msg_length;
272 };
273
274 struct lance_tx_head
275 {
276 union {
277 Address base;
278 unsigned char addr[4];
279 } u;
280 short buf_length; /* 2s complement */
281 short misc;
282 };
283
284 struct lance_interface
285 {
286 struct lance_init_block init_block;
287 struct lance_rx_head rx_ring[RX_RING_SIZE];
288 struct lance_tx_head tx_ring[TX_RING_SIZE];
289 unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN];
290 unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN];
291 };
292
293 /* =============== global variables =============== */
294 static struct lance_interface *lp;
295 static char lance[sizeof(struct lance_interface)+8];
296 static int rx_slot_nr = 0; /* Rx-slot number */
297 static int tx_slot_nr = 0; /* Tx-slot number */
298 static int cur_tx_slot_nr = 0; /* Tx-slot number */
299 static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
300 static char *progname;
301
302
303 /*===========================================================================*
304 * lance_task *
305 *===========================================================================*/
306 void main( int argc, char **argv )
307 {
308 message m;
309 int i,irq,r, tasknr;
310 ether_card_t *ec;
311 long v;
312 int fkeys, sfkeys;
313 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
314
315 env_setargs( argc, argv );
316
317 fkeys = sfkeys = 0; bit_set( sfkeys, 7 );
318
319 if ( (r = fkey_map(&fkeys, &sfkeys)) != OK )
320 printf( "Error registering key\n" );
321
322 if((eth_tasknr=getprocnr()) < 0)
323 panic("lance","couldn't get own proc nr", i);
324
325 v= 0;
326 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
327 eth_ign_proto= htons((u16_t) v);
328
329 /* Try to notify inet that we are present (again) */
330 r = findproc("inet", &tasknr);
331 if (r == OK)
332 notify(tasknr);
333
334 while (TRUE)
335 {
336 for (i=0;i<EC_PORT_NR_MAX;++i)
337 {
338 ec= &ec_table[i];
339 if (ec->ec_irq != 0)
340 sys_irqenable(&ec->ec_hook);
341 }
342
343 if ((r= receive(ANY, &m)) != OK)
344 panic( "lance", "receive failed", r);
345
346 for (i=0;i<EC_PORT_NR_MAX;++i)
347 {
348 ec= &ec_table[i];
349 if (ec->ec_irq != 0)
350 sys_irqdisable(&ec->ec_hook);
351 }
352
353 /*printf( "." );*/
354
355 switch (m.m_type){
356 case DEV_PING: notify(m.m_source); continue;
357 case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
358 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
359 case DL_READ: do_vread(&m, FALSE); break;
360 case DL_READV: do_vread(&m, TRUE); break;
361 case DL_INIT: do_init(&m); break;
362 case DL_GETSTAT: do_getstat(&m); break;
363 case DL_STOP: do_stop(&m); break;
364 case DL_GETNAME: do_getname(&m); break;
365 case FKEY_PRESSED: lance_dump(); break;
366 /*case HARD_STOP: lance_stop(); break;*/
367 case SYS_SIG:
368 {
369 sigset_t set = m.NOTIFY_ARG;
370 if ( sigismember( &set, SIGKSTOP ) )
371 lance_stop();
372 }
373 break;
374 case HARD_INT:
375 for (i=0;i<EC_PORT_NR_MAX;++i)
376 {
377 ec= &ec_table[i];
378 if (ec->mode != EC_ENABLED)
379 continue;
380
381 /*
382 printf( "#.\n" );
383 */
384
385 irq=ec->ec_irq;
386 /*if (ec->ec_int_pending)*/
387 {
388 ec->ec_int_pending = 0;
389 ec_check_ints(ec);
390 do_int(ec);
391 }
392 }
393 break;
394 default:
395 panic( "lance", "illegal message", m.m_type);
396 }
397 }
398 }
399
400 /*===========================================================================*
401 * lance_dump *
402 *===========================================================================*/
403 static void lance_dump()
404 {
405 ether_card_t *ec;
406 int i, isr;
407 unsigned short ioaddr;
408
409 printf("\n");
410 for (i= 0, ec = &ec_table[0]; i<EC_PORT_NR_MAX; i++, ec++)
411 {
412 if (ec->mode == EC_DISABLED)
413 printf("lance port %d is disabled\n", i);
414 else if (ec->mode == EC_SINK)
415 printf("lance port %d is in sink mode\n", i);
416
417 if (ec->mode != EC_ENABLED)
418 continue;
419
420 printf("lance statistics of port %d:\n", i);
421
422 printf("recvErr :%8ld\t", ec->eth_stat.ets_recvErr);
423 printf("sendErr :%8ld\t", ec->eth_stat.ets_sendErr);
424 printf("OVW :%8ld\n", ec->eth_stat.ets_OVW);
425
426 printf("CRCerr :%8ld\t", ec->eth_stat.ets_CRCerr);
427 printf("frameAll :%8ld\t", ec->eth_stat.ets_frameAll);
428 printf("missedP :%8ld\n", ec->eth_stat.ets_missedP);
429
430 printf("packetR :%8ld\t", ec->eth_stat.ets_packetR);
431 printf("packetT :%8ld\t", ec->eth_stat.ets_packetT);
432 printf("transDef :%8ld\n", ec->eth_stat.ets_transDef);
433
434 printf("collision :%8ld\t", ec->eth_stat.ets_collision);
435 printf("transAb :%8ld\t", ec->eth_stat.ets_transAb);
436 printf("carrSense :%8ld\n", ec->eth_stat.ets_carrSense);
437
438 printf("fifoUnder :%8ld\t", ec->eth_stat.ets_fifoUnder);
439 printf("fifoOver :%8ld\t", ec->eth_stat.ets_fifoOver);
440 printf("CDheartbeat:%8ld\n", ec->eth_stat.ets_CDheartbeat);
441
442 printf("OWC :%8ld\t", ec->eth_stat.ets_OWC);
443
444 ioaddr = ec->ec_port;
445 out_word(ioaddr+LANCE_ADDR, 0x00);
446 isr=in_word(ioaddr+LANCE_DATA);
447 printf("isr = 0x%x + 0x%x, flags = 0x%x\n", isr,
448 in_word(ioaddr+LANCE_DATA), ec->flags);
449
450 printf("irq = %d\tioadr = %d\n", ec->ec_irq, ec->ec_port);
451 }
452 }
453
454 /*===========================================================================*
455 * lance_stop *
456 *===========================================================================*/
457 static void lance_stop()
458 {
459 message mess;
460 int i;
461
462 for (i= 0; i<EC_PORT_NR_MAX; i++)
463 {
464 if (ec_table[i].mode != EC_ENABLED)
465 continue;
466 mess.m_type= DL_STOP;
467 mess.DL_PORT= i;
468 do_stop(&mess);
469 }
470
471 /*printf("LANCE driver stopped.\n");*/
472
473 sys_exit( 0 );
474 }
475
476
477 /*===========================================================================*
478 * do_init *
479 *===========================================================================*/
480 static void do_init(mp)
481 message *mp;
482 {
483 int port;
484 ether_card_t *ec;
485 message reply_mess;
486
487 pci_init();
488
489 port = mp->DL_PORT;
490 if (port < 0 || port >= EC_PORT_NR_MAX)
491 {
492 reply_mess.m_type= DL_INIT_REPLY;
493 reply_mess.m3_i1= ENXIO;
494 mess_reply(mp, &reply_mess);
495 return;
496 }
497 ec= &ec_table[port];
498 strcpy(ec->port_name, "eth_card#0");
499 ec->port_name[9] += port;
500 if (ec->mode == EC_DISABLED)
501 {
502 /* This is the default, try to (re)locate the device. */
503 /* only try to enable if memory is correct for DMA */
504 if ( CORRECT_DMA_MEM() )
505 {
506 conf_hw(ec);
507 }
508 else
509 {
510 report( "LANCE", "DMA denied because address out of range", NO_NUM );
511 }
512
513 if (ec->mode == EC_DISABLED)
514 {
515 /* Probe failed, or the device is configured off. */
516 reply_mess.m_type= DL_INIT_REPLY;
517 reply_mess.m3_i1= ENXIO;
518 mess_reply(mp, &reply_mess);
519 return;
520 }
521 if (ec->mode == EC_ENABLED)
522 ec_init(ec);
523 }
524
525 if (ec->mode == EC_SINK)
526 {
527 ec->mac_address.ea_addr[0] =
528 ec->mac_address.ea_addr[1] =
529 ec->mac_address.ea_addr[2] =
530 ec->mac_address.ea_addr[3] =
531 ec->mac_address.ea_addr[4] =
532 ec->mac_address.ea_addr[5] = 0;
533 ec_confaddr(ec);
534 reply_mess.m_type = DL_INIT_REPLY;
535 reply_mess.m3_i1 = mp->DL_PORT;
536 reply_mess.m3_i2 = EC_PORT_NR_MAX;
537 *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
538 mess_reply(mp, &reply_mess);
539 return;
540 }
541 assert(ec->mode == EC_ENABLED);
542 assert(ec->flags & ECF_ENABLED);
543
544 ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD);
545
546 if (mp->DL_MODE & DL_PROMISC_REQ)
547 ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD;
548 if (mp->DL_MODE & DL_MULTI_REQ)
549 ec->flags |= ECF_MULTI;
550 if (mp->DL_MODE & DL_BROAD_REQ)
551 ec->flags |= ECF_BROAD;
552
553 ec->client = mp->m_source;
554 ec_reinit(ec);
555
556 reply_mess.m_type = DL_INIT_REPLY;
557 reply_mess.m3_i1 = mp->DL_PORT;
558 reply_mess.m3_i2 = EC_PORT_NR_MAX;
559 *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
560
561 mess_reply(mp, &reply_mess);
562 }
563
564
565 /*===========================================================================*
566 * do_int *
567 *===========================================================================*/
568 static void do_int(ec)
569 ether_card_t *ec;
570 {
571 if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))
572 reply(ec, OK, TRUE);
573 }
574
575 #if 0
576 /*===========================================================================*
577 * ec_handler *
578 *===========================================================================*/
579 static int ec_handler(hook)
580 irq_hook_t *hook;
581 {
582 /* LANCE interrupt, send message and reenable interrupts. */
583 #if 0
584 printf(">> ec_handler(): \n");
585 #endif
586
587 structof(ether_card_t, ec_hook, hook)->ec_int_pending= 1;
588
589 notify(eth_tasknr);
590
591 return 0;
592 }
593 #endif
594
595 /*===========================================================================*
596 * conf_hw *
597 *===========================================================================*/
598 static void conf_hw(ec)
599 ether_card_t *ec;
600 {
601 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
602
603 int ifnr;
604 ec_conf_t *ecp;
605
606 ec->mode= EC_DISABLED; /* Superfluous */
607 ifnr= ec-ec_table;
608
609 ecp= &ec_conf[ifnr];
610 update_conf(ec, ecp);
611 if (ec->mode != EC_ENABLED)
612 return;
613
614 if (!lance_probe(ec))
615 {
616 printf("%s: No ethernet card found on PCI-BIOS info.\n",
617 ec->port_name);
618 ec->mode= EC_DISABLED;
619 return;
620 }
621
622 /* Allocate a memory segment, programmed I/O should set the
623 * memory segment (linmem) to zero.
624 */
625 if (ec->ec_linmem != 0)
626 {
627 assert( 0 );
628 /*phys2seg(&ec->ec_memseg, &ec->ec_memoff, ec->ec_linmem);*/
629 }
630
631 /* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;
632
633 ec->flags = ECF_EMPTY;
634 ec->eth_stat = empty_stat;
635 }
636
637
638 /*===========================================================================*
639 * update_conf *
640 *===========================================================================*/
641 static void update_conf(ec, ecp)
642 ether_card_t *ec;
643 ec_conf_t *ecp;
644 {
645 long v;
646 static char ec_fmt[] = "x:d:x:x";
647
648 /* Get the default settings and modify them from the environment. */
649 ec->mode= EC_SINK;
650 v= ecp->ec_port;
651 switch (env_parse(ecp->ec_envvar, ec_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
652 case EP_OFF:
653 ec->mode= EC_DISABLED;
654 break;
655 case EP_ON:
656 case EP_SET:
657 ec->mode= EC_ENABLED; /* Might become disabled if
658 * all probes fail */
659 break;
660 }
661
662 ec->ec_port= v;
663
664 v= ecp->ec_irq | DEI_DEFAULT;
665 (void) env_parse(ecp->ec_envvar, ec_fmt, 1, &v, 0L,
666 (long) NR_IRQ_VECTORS - 1);
667 ec->ec_irq= v;
668
669 v= ecp->ec_mem;
670 (void) env_parse(ecp->ec_envvar, ec_fmt, 2, &v, 0L, 0xFFFFFL);
671 ec->ec_linmem= v;
672
673 v= 0;
674 (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L);
675 ec->ec_ramsize= v;
676 }
677
678
679 /*===========================================================================*
680 * ec_init *
681 *===========================================================================*/
682 static void ec_init(ec)
683 ether_card_t *ec;
684 {
685 int i, r;
686
687 /* General initialization */
688 ec->flags = ECF_EMPTY;
689 /*disable_irq(ec->ec_irq);*/
690 lance_init_card(ec); /* Get mac_address, etc ...*/
691
692 ec_confaddr(ec);
693
694 #if VERBOSE
695 printf("%s: Ethernet address ", ec->port_name);
696 for (i= 0; i < 6; i++)
697 printf("%x%c", ec->mac_address.ea_addr[i],
698 i < 5 ? ':' : '\n');
699 #endif
700
701 /* Finish the initialization */
702 ec->flags |= ECF_ENABLED;
703
704 /* Set the interrupt handler */
705 /*put_irq_handler(&ec->ec_hook, ec->ec_irq, ec_handler);*/
706 ec->ec_hook = ec->ec_irq;
707 if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)
708 printf("lance: error, couldn't set IRQ policy: %d\n", r);
709
710 /* enable_irq(ec->ec_irq); */
711
712 /* enter_kdebug(">> ec_init():"); */
713
714 return;
715 }
716
717
718 /*===========================================================================*
719 * reply *
720 *===========================================================================*/
721 static void reply(ec, err, may_block)
722 ether_card_t *ec;
723 int err;
724 int may_block;
725 {
726 message reply;
727 int status,r;
728 clock_t now;
729
730 status = 0;
731 if (ec->flags & ECF_PACK_SEND)
732 status |= DL_PACK_SEND;
733 if (ec->flags & ECF_PACK_RECV)
734 status |= DL_PACK_RECV;
735
736 reply.m_type = DL_TASK_REPLY;
737 reply.DL_PORT = ec - ec_table;
738 reply.DL_PROC = ec->client;
739 reply.DL_STAT = status | ((u32_t) err << 16);
740 reply.DL_COUNT = ec->read_s;
741 #if 1
742 if ((r=getuptime(&now)) != OK)
743 panic("lance", "getuptime() failed:", r);
744 reply.DL_CLCK = now;
745 #else
746 reply.DL_CLCK = 0;
747 #endif
748
749 r = send(ec->client, &reply);
750 #if 1
751 if (r == ELOCKED && may_block)
752 {
753 /* enter_kdebug(">> lance_task: ELOCKED!"); */
754 return;
755 }
756 #endif
757 if (r < 0)
758 panic( "lance", "send failed:", r);
759
760 ec->read_s = 0;
761 ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);
762 }
763
764
765 /*===========================================================================*
766 * mess_reply *
767 *===========================================================================*/
768 static void mess_reply(req, reply_mess)
769 message *req;
770 message *reply_mess;
771 {
772 if (send(req->m_source, reply_mess) != OK)
773 panic( "lance", "unable to mess_reply", NO_NUM);
774 }
775
776
777 /*===========================================================================*
778 * ec_confaddr *
779 *===========================================================================*/
780 static void ec_confaddr(ec)
781 ether_card_t *ec;
782 {
783 int i;
784 char eakey[16];
785 static char eafmt[]= "x:x:x:x:x:x";
786 long v;
787
788 /* User defined ethernet address? */
789 strcpy(eakey, ec_conf[ec-ec_table].ec_envvar);
790 strcat(eakey, "_EA");
791
792 for (i= 0; i < 6; i++)
793 {
794 v= ec->mac_address.ea_addr[i];
795 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
796 break;
797 ec->mac_address.ea_addr[i]= v;
798 }
799
800 if (i != 0 && i != 6)
801 {
802 /* It's all or nothing; force a panic. */
803 (void) env_parse(eakey, "?", 0, &v, 0L, 0L);
804 }
805 }
806
807
808 /*===========================================================================*
809 * ec_reinit *
810 *===========================================================================*/
811 static void ec_reinit(ec)
812 ether_card_t *ec;
813 {
814 int i;
815 unsigned short ioaddr = ec->ec_port;
816
817 out_word(ioaddr+LANCE_ADDR, 0x0);
818 (void)in_word(ioaddr+LANCE_ADDR);
819 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
820
821 /* purge Tx-ring */
822 tx_slot_nr = cur_tx_slot_nr = 0;
823 for (i=0; i<TX_RING_SIZE; i++) {
824 lp->tx_ring[i].u.base = 0;
825 isstored[i]=0;
826 }
827
828 /* re-init Rx-ring */
829 rx_slot_nr = 0;
830 for (i=0; i<RX_RING_SIZE; i++)
831 {
832 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
833 lp->rx_ring[i].u.addr[3] |= 0x80;
834 }
835
836 /* Set 'Receive Mode' */
837 if (ec->flags & ECF_PROMISC)
838 {
839 out_word(ioaddr+LANCE_ADDR, 0xf);
840 out_word(ioaddr+LANCE_DATA, 0x8000);
841 }
842 else
843 {
844 if (ec->flags & (ECF_BROAD | ECF_MULTI))
845 {
846 out_word(ioaddr+LANCE_ADDR, 0xf);
847 out_word(ioaddr+LANCE_DATA, 0x0000);
848 }
849 else
850 {
851 out_word(ioaddr+LANCE_ADDR, 0xf);
852 out_word(ioaddr+LANCE_DATA, 0x4000);
853 }
854 }
855
856 out_word(ioaddr+LANCE_ADDR, 0x0);
857 (void)in_word(ioaddr+LANCE_ADDR);
858 out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */
859
860 return;
861 }
862
863 /*===========================================================================*
864 * ec_check_ints *
865 *===========================================================================*/
866 static void ec_check_ints(ec)
867 ether_card_t *ec;
868 {
869 int must_restart=0;
870 int check,status;
871 int isr=0x0000;
872 unsigned short ioaddr = ec->ec_port;
873
874 if (!(ec->flags & ECF_ENABLED))
875 panic( "lance", "got premature interrupt", NO_NUM);
876
877 for (;;)
878 {
879 #if 0
880 printf("ETH: Reading ISR...");
881 #endif
882 out_word(ioaddr+LANCE_ADDR, 0x00);
883 isr=in_word(ioaddr+LANCE_DATA);
884 if (isr & 0x8600)
885 out_word( ioaddr+LANCE_DATA, isr & ~0x004f);
886 out_word(ioaddr+LANCE_DATA, 0x7940);
887 #if 0
888 printf("ISR=0x%x...",in_word(ioaddr+LANCE_DATA));
889 #endif
890 #define ISR_WINT 0x0200
891 #define ISR_RINT 0x0400
892 #define ISR_RERR 0x1000
893 #define ISR_WERR 0x4000
894 #define ISR_ERR 0x8000
895 #define ISR_RST 0x0000
896
897 if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000)
898 {
899 #if 0
900 printf("OK\n");
901 #endif
902 break;
903 }
904
905 if (isr & ISR_RERR)
906 {
907 #if 0
908 printf("RERR\n");
909 #endif
910 ec->eth_stat.ets_recvErr++;
911 }
912 if ((isr & ISR_WERR) || (isr & ISR_WINT))
913 {
914 if (isr & ISR_WERR)
915 {
916 #if 0
917 printf("WERR\n");
918 #endif
919 ec->eth_stat.ets_sendErr++;
920 }
921 if (isr & ISR_WINT)
922 {
923 #if 0
924 printf("WINT\n");
925 #endif
926 /* status check: restart if needed. */
927 status = lp->tx_ring[cur_tx_slot_nr].u.base;
928
929 /* ??? */
930 if (status & 0x40000000)
931 {
932 status = lp->tx_ring[cur_tx_slot_nr].misc;
933 ec->eth_stat.ets_sendErr++;
934 if (status & 0x0400)
935 ec->eth_stat.ets_transAb++;
936 if (status & 0x0800)
937 ec->eth_stat.ets_carrSense++;
938 if (status & 0x1000)
939 ec->eth_stat.ets_OWC++;
940 if (status & 0x4000)
941 {
942 ec->eth_stat.ets_fifoUnder++;
943 must_restart=1;
944 }
945 }
946 else
947 {
948 if (status & 0x18000000)
949 ec->eth_stat.ets_collision++;
950 ec->eth_stat.ets_packetT++;
951 }
952 }
953 /* transmit a packet on the next slot if it exists. */
954 check = 0;
955 if (isstored[cur_tx_slot_nr]==1)
956 {
957 /* free the tx-slot just transmitted */
958 isstored[cur_tx_slot_nr]=0;
959 cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK;
960
961 /* next tx-slot is ready? */
962 if (isstored[cur_tx_slot_nr]==1)
963 check=1;
964 else
965 check=0;
966 }
967 else
968 {
969 panic( "lance", "got premature WINT...", NO_NUM);
970 }
971 if (check==1)
972 {
973 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
974 out_word(ioaddr+LANCE_ADDR, 0x0000);
975 out_word(ioaddr+LANCE_DATA, 0x0048);
976 }
977 else
978 if (check==-1)
979 continue;
980 /* we set a buffered message in the slot if it exists. */
981 /* and transmit it, if needed. */
982 if (ec->flags & ECF_SEND_AVAIL)
983 ec_send(ec);
984 }
985 if (isr & ISR_RINT)
986 {
987 #if 0
988 printf("RINT\n");
989 #endif
990 ec_recv(ec);
991 }
992
993 if (isr & ISR_RST)
994 {
995 ec->flags = ECF_STOPPED;
996 break;
997 }
998
999 /* ??? cf. lance driver on linux */
1000 if (must_restart == 1)
1001 {
1002 #if 0
1003 printf("ETH: restarting...\n");
1004 #endif
1005 out_word(ioaddr+LANCE_ADDR, 0x0);
1006 (void)in_word(ioaddr+LANCE_ADDR);
1007 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1008 out_word(ioaddr+LANCE_DATA, 0x2); /* start */
1009 }
1010 }
1011
1012 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1013 {
1014 #if 0
1015 printf("ETH: resetting...\n");
1016 #endif
1017 ec_reset(ec);
1018 }
1019 }
1020
1021 /*===========================================================================*
1022 * ec_reset *
1023 *===========================================================================*/
1024 static void ec_reset(ec)
1025 ether_card_t *ec;
1026 {
1027 /* Stop/start the chip, and clear all RX,TX-slots */
1028 unsigned short ioaddr = ec->ec_port;
1029 int i;
1030
1031 out_word(ioaddr+LANCE_ADDR, 0x0);
1032 (void)in_word(ioaddr+LANCE_ADDR);
1033 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1034 out_word(ioaddr+LANCE_DATA, 0x2); /* start */
1035
1036 /* purge Tx-ring */
1037 tx_slot_nr = cur_tx_slot_nr = 0;
1038 for (i=0; i<TX_RING_SIZE; i++) {
1039 lp->tx_ring[i].u.base = 0;
1040 isstored[i]=0;
1041 }
1042
1043 /* re-init Rx-ring */
1044 rx_slot_nr = 0;
1045 for (i=0; i<RX_RING_SIZE; i++)
1046 {
1047 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
1048 lp->rx_ring[i].u.addr[3] |= 0x80;
1049 }
1050
1051 /* store a buffered message on the slot if exists */
1052 ec_send(ec);
1053 ec->flags &= ~ECF_STOPPED;
1054 }
1055
1056 /*===========================================================================*
1057 * ec_send *
1058 *===========================================================================*/
1059 static void ec_send(ec)
1060 ether_card_t *ec;
1061 {
1062 /* from ec_check_ints() or ec_reset(). */
1063 /* this function proccesses the buffered message. (slot/transmit) */
1064 if (!(ec->flags & ECF_SEND_AVAIL))
1065 return;
1066
1067 ec->flags &= ~ECF_SEND_AVAIL;
1068 switch(ec->sendmsg.m_type)
1069 {
1070 case DL_WRITE: do_vwrite(&ec->sendmsg, TRUE, FALSE); break;
1071 case DL_WRITEV: do_vwrite(&ec->sendmsg, TRUE, TRUE); break;
1072 default:
1073 panic( "lance", "wrong type:", ec->sendmsg.m_type);
1074 break;
1075 }
1076 }
1077
1078 /*===========================================================================*
1079 * do_vread *
1080 *===========================================================================*/
1081 static void do_vread(mp, vectored)
1082 message *mp;
1083 int vectored;
1084 {
1085 int port, count, size;
1086 ether_card_t *ec;
1087
1088 port = mp->DL_PORT;
1089 count = mp->DL_COUNT;
1090 ec= &ec_table[port];
1091 ec->client= mp->DL_PROC;
1092
1093 if (vectored)
1094 {
1095 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
1096 (count > IOVEC_NR ? IOVEC_NR : count) *
1097 sizeof(iovec_t), ec->read_iovec.iod_iovec);
1098 ec->read_iovec.iod_iovec_s = count;
1099 ec->read_iovec.iod_proc_nr = mp->DL_PROC;
1100 ec->read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
1101
1102 ec->tmp_iovec = ec->read_iovec;
1103 size= calc_iovec_size(&ec->tmp_iovec);
1104 }
1105 else
1106 {
1107 ec->read_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
1108 ec->read_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
1109 ec->read_iovec.iod_iovec_s = 1;
1110 ec->read_iovec.iod_proc_nr = mp->DL_PROC;
1111 ec->read_iovec.iod_iovec_addr = 0;
1112
1113 size= count;
1114 }
1115 ec->flags |= ECF_READING;
1116
1117 ec_recv(ec);
1118
1119 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1120 ec_reset(ec);
1121 reply(ec, OK, FALSE);
1122 }
1123
1124 /*===========================================================================*
1125 * ec_recv *
1126 *===========================================================================*/
1127 static void ec_recv(ec)
1128 ether_card_t *ec;
1129 {
1130 vir_bytes length;
1131 int packet_processed;
1132 int status;
1133 unsigned short ioaddr = ec->ec_port;
1134
1135 if ((ec->flags & ECF_READING)==0)
1136 return;
1137 if (!(ec->flags & ECF_ENABLED))
1138 return;
1139
1140 /* we check all the received slots until find a properly received packet */
1141 packet_processed = FALSE;
1142 while (!packet_processed)
1143 {
1144 status = lp->rx_ring[rx_slot_nr].u.base >> 24;
1145 if ( (status & 0x80) == 0x00 )
1146 {
1147 status = lp->rx_ring[rx_slot_nr].u.base >> 24;
1148
1149 /* ??? */
1150 if (status != 0x03)
1151 {
1152 if (status & 0x01)
1153 ec->eth_stat.ets_recvErr++;
1154 if (status & 0x04)
1155 ec->eth_stat.ets_fifoOver++;
1156 if (status & 0x08)
1157 ec->eth_stat.ets_CRCerr++;
1158 if (status & 0x10)
1159 ec->eth_stat.ets_OVW++;
1160 if (status & 0x20)
1161 ec->eth_stat.ets_frameAll++;
1162 length = 0;
1163 }
1164 else
1165 {
1166 ec->eth_stat.ets_packetR++;
1167 length = lp->rx_ring[rx_slot_nr].msg_length;
1168 }
1169 if (length > 0)
1170 {
1171 ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]),
1172 &ec->read_iovec, 0, length);
1173
1174 ec->read_s = length;
1175 ec->flags |= ECF_PACK_RECV;
1176 ec->flags &= ~ECF_READING;
1177 packet_processed = TRUE;
1178 }
1179 /* set up this slot again, and we move to the next slot */
1180 lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;
1181 lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;
1182
1183 out_word(ioaddr+LANCE_ADDR, 0x00);
1184 out_word(ioaddr+LANCE_DATA, 0x7940);
1185
1186 rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK;
1187 }
1188 else
1189 break;
1190 }
1191 }
1192
1193 /*===========================================================================*
1194 * do_vwrite *
1195 *===========================================================================*/
1196 static void do_vwrite(mp, from_int, vectored)
1197 message *mp;
1198 int from_int;
1199 int vectored;
1200 {
1201 int port, count, check;
1202 ether_card_t *ec;
1203 unsigned short ioaddr;
1204
1205 port = mp->DL_PORT;
1206 count = mp->DL_COUNT;
1207 ec = &ec_table[port];
1208 ec->client= mp->DL_PROC;
1209
1210 if (isstored[tx_slot_nr]==1)
1211 {
1212 /* all slots are used, so this message is buffered */
1213 ec->sendmsg= *mp;
1214 ec->flags |= ECF_SEND_AVAIL;
1215 reply(ec, OK, FALSE);
1216 return;
1217 }
1218
1219 /* convert the message to write_iovec */
1220 if (vectored)
1221 {
1222 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
1223 (count > IOVEC_NR ? IOVEC_NR : count) *
1224 sizeof(iovec_t), ec->write_iovec.iod_iovec);
1225
1226 ec->write_iovec.iod_iovec_s = count;
1227 ec->write_iovec.iod_proc_nr = mp->DL_PROC;
1228 ec->write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
1229
1230 ec->tmp_iovec = ec->write_iovec;
1231 ec->write_s = calc_iovec_size(&ec->tmp_iovec);
1232 }
1233 else
1234 {
1235 ec->write_iovec.iod_iovec[0].iov_addr = (vir_bytes) mp->DL_ADDR;
1236 ec->write_iovec.iod_iovec[0].iov_size = mp->DL_COUNT;
1237
1238 ec->write_iovec.iod_iovec_s = 1;
1239 ec->write_iovec.iod_proc_nr = mp->DL_PROC;
1240 ec->write_iovec.iod_iovec_addr = 0;
1241
1242 ec->write_s = mp->DL_COUNT;
1243 }
1244
1245 /* copy write_iovec to the slot on DMA address */
1246 ec_user2nic(ec, &ec->write_iovec, 0,
1247 (int)(lp->tbuf[tx_slot_nr]), ec->write_s);
1248 /* set-up for transmitting, and transmit it if needed. */
1249 lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s;
1250 lp->tx_ring[tx_slot_nr].misc = 0x0;
1251 lp->tx_ring[tx_slot_nr].u.base
1252 = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff;
1253 isstored[tx_slot_nr]=1;
1254 if (cur_tx_slot_nr == tx_slot_nr)
1255 check=1;
1256 else
1257 check=0;
1258 tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK;
1259
1260 if (check == 1)
1261 {
1262 ioaddr = ec->ec_port;
1263 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
1264 out_word(ioaddr+LANCE_ADDR, 0x0000);
1265 out_word(ioaddr+LANCE_DATA, 0x0048);
1266 }
1267
1268 ec->flags |= ECF_PACK_SEND;
1269
1270 /* reply by calling do_int() if this function is called from interrupt. */
1271 if (from_int)
1272 return;
1273 reply(ec, OK, FALSE);
1274 }
1275
1276
1277 /*===========================================================================*
1278 * get_userdata *
1279 *===========================================================================*/
1280 static void get_userdata(user_proc, user_addr, count, loc_addr)
1281 int user_proc;
1282 vir_bytes user_addr;
1283 vir_bytes count;
1284 void *loc_addr;
1285 {
1286 /*
1287 phys_bytes src;
1288
1289 src = numap_local(user_proc, user_addr, count);
1290 if (!src)
1291 panic( "lance", "umap failed", NO_NUM);
1292
1293 phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
1294 */
1295 int cps;
1296 cps = sys_datacopy(user_proc, user_addr, SELF, (vir_bytes) loc_addr, count);
1297 if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
1298 }
1299
1300 /*===========================================================================*
1301 * ec_user2nic *
1302 *===========================================================================*/
1303 static void ec_user2nic(ec, iovp, offset, nic_addr, count)
1304 ether_card_t *ec;
1305 iovec_dat_t *iovp;
1306 vir_bytes offset;
1307 int nic_addr;
1308 vir_bytes count;
1309 {
1310 /*phys_bytes phys_hw, phys_user;*/
1311 int bytes, i, r;
1312
1313 /*
1314 phys_hw = vir2phys(nic_addr);
1315 */
1316 i= 0;
1317 while (count > 0)
1318 {
1319 if (i >= IOVEC_NR)
1320 {
1321 ec_next_iovec(iovp);
1322 i= 0;
1323 continue;
1324 }
1325 if (offset >= iovp->iod_iovec[i].iov_size)
1326 {
1327 offset -= iovp->iod_iovec[i].iov_size;
1328 i++;
1329 continue;
1330 }
1331 bytes = iovp->iod_iovec[i].iov_size - offset;
1332 if (bytes > count)
1333 bytes = count;
1334
1335 /*
1336 phys_user = numap_local(iovp->iod_proc_nr,
1337 iovp->iod_iovec[i].iov_addr + offset, bytes);
1338
1339 phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
1340 */
1341 if ( (r=sys_datacopy(iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset,
1342 SELF, nic_addr, count )) != OK )
1343 panic( "lance", "sys_datacopy failed", r );
1344
1345 count -= bytes;
1346 nic_addr += bytes;
1347 offset += bytes;
1348 }
1349 }
1350
1351 /*===========================================================================*
1352 * ec_nic2user *
1353 *===========================================================================*/
1354 static void ec_nic2user(ec, nic_addr, iovp, offset, count)
1355 ether_card_t *ec;
1356 int nic_addr;
1357 iovec_dat_t *iovp;
1358 vir_bytes offset;
1359 vir_bytes count;
1360 {
1361 /*phys_bytes phys_hw, phys_user;*/
1362 int bytes, i, r;
1363
1364 /*phys_hw = vir2phys(nic_addr);*/
1365
1366 i= 0;
1367 while (count > 0)
1368 {
1369 if (i >= IOVEC_NR)
1370 {
1371 ec_next_iovec(iovp);
1372 i= 0;
1373 continue;
1374 }
1375 if (offset >= iovp->iod_iovec[i].iov_size)
1376 {
1377 offset -= iovp->iod_iovec[i].iov_size;
1378 i++;
1379 continue;
1380 }
1381 bytes = iovp->iod_iovec[i].iov_size - offset;
1382 if (bytes > count)
1383 bytes = count;
1384 /*
1385 phys_user = numap_local(iovp->iod_proc_nr,
1386 iovp->iod_iovec[i].iov_addr + offset, bytes);
1387
1388 phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
1389 */
1390 if ( (r=sys_datacopy( SELF, nic_addr, iovp->iod_proc_nr, iovp->iod_iovec[i].iov_addr + offset, bytes )) != OK )
1391 panic( "lance", "sys_datacopy failed: ", r );
1392
1393 count -= bytes;
1394 nic_addr += bytes;
1395 offset += bytes;
1396 }
1397 }
1398
1399
1400 /*===========================================================================*
1401 * calc_iovec_size *
1402 *===========================================================================*/
1403 static int calc_iovec_size(iovp)
1404 iovec_dat_t *iovp;
1405 {
1406 int size,i;
1407
1408 size = i = 0;
1409
1410 while (i < iovp->iod_iovec_s)
1411 {
1412 if (i >= IOVEC_NR)
1413 {
1414 ec_next_iovec(iovp);
1415 i= 0;
1416 continue;
1417 }
1418 size += iovp->iod_iovec[i].iov_size;
1419 i++;
1420 }
1421
1422 return size;
1423 }
1424
1425 /*===========================================================================*
1426 * ec_next_iovec *
1427 *===========================================================================*/
1428 static void ec_next_iovec(iovp)
1429 iovec_dat_t *iovp;
1430 {
1431 iovp->iod_iovec_s -= IOVEC_NR;
1432 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1433
1434 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1435 (iovp->iod_iovec_s > IOVEC_NR ?
1436 IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_t),
1437 iovp->iod_iovec);
1438 }
1439
1440
1441 /*===========================================================================*
1442 * do_getstat *
1443 *===========================================================================*/
1444 static void do_getstat(mp)
1445 message *mp;
1446 {
1447 int port;
1448 ether_card_t *ec;
1449
1450 port = mp->DL_PORT;
1451 if (port < 0 || port >= EC_PORT_NR_MAX)
1452 panic( "lance", "illegal port", port);
1453
1454 ec= &ec_table[port];
1455 ec->client= mp->DL_PROC;
1456
1457 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
1458 (vir_bytes) sizeof(ec->eth_stat), &ec->eth_stat);
1459 reply(ec, OK, FALSE);
1460 }
1461
1462 /*===========================================================================*
1463 * put_userdata *
1464 *===========================================================================*/
1465 static void put_userdata(user_proc, user_addr, count, loc_addr)
1466 int user_proc;
1467 vir_bytes user_addr;
1468 vir_bytes count;
1469 void *loc_addr;
1470 {
1471 /*phys_bytes dst;
1472
1473 dst = numap_local(user_proc, user_addr, count);
1474 if (!dst)
1475 panic( "lance", "umap failed", NO_NUM);
1476
1477 phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
1478 */
1479 int cps;
1480 cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
1481 if (cps != OK) printf("lance: warning, scopy failed: %d\n", cps);
1482 }
1483
1484 /*===========================================================================*
1485 * do_stop *
1486 *===========================================================================*/
1487 static void do_stop(mp)
1488 message *mp;
1489 {
1490 int port;
1491 ether_card_t *ec;
1492 unsigned short ioaddr;
1493
1494 port = mp->DL_PORT;
1495 if (port < 0 || port >= EC_PORT_NR_MAX)
1496 panic( "lance", "illegal port", port);
1497 ec = &ec_table[port];
1498
1499 if (!(ec->flags & ECF_ENABLED))
1500 return;
1501
1502 ioaddr = ec->ec_port;
1503
1504 out_word(ioaddr+LANCE_ADDR, 0x0);
1505 (void)in_word(ioaddr+LANCE_ADDR);
1506 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1507 out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */
1508
1509 ec->flags = ECF_EMPTY;
1510 }
1511
1512 static void getAddressing(devind, ec)
1513 int devind;
1514 ether_card_t *ec;
1515 {
1516 unsigned int membase, ioaddr;
1517 int reg, irq;
1518
1519 for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)
1520 {
1521 ioaddr = pci_attr_r32(devind, reg);
1522
1523 if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0
1524 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
1525 continue;
1526 /* Strip the I/O address out of the returned value */
1527 ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
1528 /* Get the memory base address */
1529 membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1);
1530 /* KK: Get the IRQ number */
1531 irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN);
1532 if (irq)
1533 irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE);
1534 /* Get the ROM base address */
1535 /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr);
1536 romaddr >>= 10;*/
1537 /* Take the first one or the one that matches in boot ROM address */
1538 /*if (pci_ioaddr == 0
1539 || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/
1540 ec->ec_linmem = membase;
1541 ec->ec_port = ioaddr;
1542 ec->ec_irq = irq;
1543 /*}*/
1544 }
1545 }
1546
1547 /*===========================================================================*
1548 * lance_probe *
1549 *===========================================================================*/
1550 static int lance_probe(ec)
1551 ether_card_t *ec;
1552 {
1553 unsigned short pci_cmd, attached = 0;
1554 unsigned short ioaddr;
1555 int lance_version, chip_version;
1556 int devind, just_one, i, r;
1557
1558 u16_t vid, did;
1559 u32_t bar;
1560 u8_t ilr;
1561 char *dname;
1562
1563 if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0)
1564 {
1565 /* Look for specific PCI device */
1566 r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev,
1567 ec->ec_pcifunc, &devind);
1568 if (r == 0)
1569 {
1570 printf("%s: no PCI found at %d.%d.%d\n",
1571 ec->port_name, ec->ec_pcibus,
1572 ec->ec_pcidev, ec->ec_pcifunc);
1573 return 0;
1574 }
1575 pci_ids(devind, &vid, &did);
1576 just_one= TRUE;
1577 }
1578 else
1579 {
1580 r= pci_first_dev(&devind, &vid, &did);
1581 if (r == 0)
1582 return 0;
1583 just_one= FALSE;
1584 }
1585
1586 for(;;)
1587 {
1588 for (i= 0; pcitab[i].vid != 0; i++)
1589 {
1590 if (pcitab[i].vid != vid)
1591 continue;
1592 if (pcitab[i].did != did)
1593 continue;
1594 if (pcitab[i].checkclass)
1595 {
1596 panic("lance",
1597 "class check not implemented", NO_NUM);
1598 }
1599 break;
1600 }
1601 if (pcitab[i].vid != 0)
1602 break;
1603
1604 if (just_one)
1605 {
1606 printf(
1607 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
1608 ec->port_name, vid, did,
1609 ec->ec_pcibus,
1610 ec->ec_pcidev, ec->ec_pcifunc);
1611 return 0;
1612 }
1613
1614 r= pci_next_dev(&devind, &vid, &did);
1615 if (!r)
1616 return 0;
1617 }
1618
1619 dname= pci_dev_name(vid, did);
1620 if (!dname)
1621 dname= "unknown device";
1622
1623 /*
1624 printf("%s: ", ec->port_name);
1625 printf("%s ", dname);
1626 printf("(%x/", vid);
1627 printf("%x) ", did);
1628 printf("at %s\n", pci_slot_name(devind));
1629 */
1630 pci_reserve(devind);
1631
1632 /* for (i = 0; pci_dev_list[i].vendor != 0; i++) {
1633 if (pci_dev_list[i].suffix == 1)
1634 {
1635 ec->ec_port = pci_dev_list[i].ioaddr;
1636 ec->ec_irq = pci_dev_list[i].irq;
1637 ec->ec_linmem = pci_dev_list[i].membase;
1638 ec->ec_bus = pci_dev_list[i].bus;
1639 ec->ec_dev = pci_dev_list[i].devfn;
1640 ec->ec_fnc =
1641 pci_dev_list[i].suffix = -1;
1642 attached = 1;
1643 break;
1644 }
1645 }
1646 if (attached == 0)
1647 return 0;
1648 */
1649 getAddressing(devind, ec);
1650
1651 /* ===== Bus Master ? ===== */
1652 /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/
1653 pci_cmd = pci_attr_r32(devind, PCI_CR);
1654 if (!(pci_cmd & PCI_COMMAND_MASTER)) {
1655 pci_cmd |= PCI_COMMAND_MASTER;
1656 /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/
1657 pci_attr_w32(devind, PCI_CR, pci_cmd);
1658 }
1659
1660 /* ===== Probe Details ===== */
1661 ioaddr = ec->ec_port;
1662
1663 out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */
1664 out_word(ioaddr+LANCE_ADDR, 0x0); /* Sw to win 0 */
1665 if (in_word(ioaddr+LANCE_DATA) != 0x4)
1666 {
1667 ec->mode=EC_DISABLED;
1668 }
1669 /* Probe Chip Version */
1670 out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */
1671 if (in_word(ioaddr+LANCE_ADDR) != 88)
1672 lance_version = 0;
1673 else
1674 {
1675 chip_version = in_word(ioaddr+LANCE_DATA);
1676 out_word(ioaddr+LANCE_ADDR, 89);
1677 chip_version |= in_word(ioaddr+LANCE_DATA) << 16;
1678 if ((chip_version & 0xfff) != 0x3)
1679 {
1680 ec->mode=EC_DISABLED;
1681 }
1682 chip_version = (chip_version >> 12) & 0xffff;
1683 for (lance_version = 1; chip_table[lance_version].id_number != 0;
1684 ++lance_version)
1685 if (chip_table[lance_version].id_number == chip_version)
1686 break;
1687 }
1688
1689 #if 0
1690 printf("%s: %s at %X:%d\n",
1691 ec->port_name, chip_table[lance_version].name,
1692 ec->ec_port, ec->ec_irq);
1693 #endif
1694
1695 return lance_version;
1696 }
1697
1698 /*===========================================================================*
1699 * do_getname *
1700 *===========================================================================*/
1701 static void do_getname(mp)
1702 message *mp;
1703 {
1704 int r;
1705
1706 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
1707 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
1708 mp->m_type= DL_NAME_REPLY;
1709 r= send(mp->m_source, mp);
1710 if (r != OK)
1711 panic("LANCE", "do_getname: send failed", r);
1712 }
1713
1714 /*===========================================================================*
1715 * lance_init_card *
1716 *===========================================================================*/
1717 static void lance_init_card(ec)
1718 ether_card_t *ec;
1719 {
1720 int i;
1721 Address l;
1722 unsigned short ioaddr = ec->ec_port;
1723
1724 /* ============= setup init_block(cf. lance_probe1) ================ */
1725 /* make sure data structure is 8-byte aligned */
1726 l = ((Address)lance + 7) & ~7;
1727 lp = (struct lance_interface *)l;
1728 lp->init_block.mode = 0x3; /* disable Rx and Tx */
1729 lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
1730 /* using multiple Rx/Tx buffer */
1731 lp->init_block.rx_ring
1732 = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
1733 lp->init_block.tx_ring
1734 = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
1735
1736 l = virt_to_bus(&lp->init_block);
1737 out_word(ioaddr+LANCE_ADDR, 0x1);
1738 (void)in_word(ioaddr+LANCE_ADDR);
1739 out_word(ioaddr+LANCE_DATA, (unsigned short)l);
1740 out_word(ioaddr+LANCE_ADDR, 0x2);
1741 (void)in_word(ioaddr+LANCE_ADDR);
1742 out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16));
1743 out_word(ioaddr+LANCE_ADDR, 0x4);
1744 (void)in_word(ioaddr+LANCE_ADDR);
1745 out_word(ioaddr+LANCE_DATA, 0x915);
1746 out_word(ioaddr+LANCE_ADDR, 0x0);
1747 (void)in_word(ioaddr+LANCE_ADDR);
1748
1749 /* ============= Get MAC address (cf. lance_probe1) ================ */
1750 for (i = 0; i < 6; ++i)
1751 ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
1752
1753 /* ============ (re)start init_block(cf. lance_reset) =============== */
1754 /* Reset the LANCE */
1755 (void)in_word(ioaddr+LANCE_RESET);
1756
1757 /* ----- Re-initialize the LANCE ----- */
1758 /* Set station address */
1759 for (i = 0; i < 6; ++i)
1760 lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i];
1761 /* Preset the receive ring headers */
1762 for (i=0; i<RX_RING_SIZE; i++) {
1763 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
1764 /* OWN */
1765 lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
1766 /* we set the top byte as the very last thing */
1767 lp->rx_ring[i].u.addr[3] = 0x80;
1768 }
1769 /* Preset the transmitting ring headers */
1770 for (i=0; i<TX_RING_SIZE; i++) {
1771 lp->tx_ring[i].u.base = 0;
1772 isstored[i] = 0;
1773 }
1774 lp->init_block.mode = 0x0; /* enable Rx and Tx */
1775
1776 l = (Address)virt_to_bus(&lp->init_block);
1777 out_word(ioaddr+LANCE_ADDR, 0x1);
1778 (void)in_word(ioaddr+LANCE_ADDR);
1779 out_word(ioaddr+LANCE_DATA, (short)l);
1780 out_word(ioaddr+LANCE_ADDR, 0x2);
1781 (void)in_word(ioaddr+LANCE_ADDR);
1782 out_word(ioaddr+LANCE_DATA, (short)(l >> 16));
1783 out_word(ioaddr+LANCE_ADDR, 0x4);
1784 (void)in_word(ioaddr+LANCE_ADDR);
1785 out_word(ioaddr+LANCE_DATA, 0x915);
1786 out_word(ioaddr+LANCE_ADDR, 0x0);
1787 (void)in_word(ioaddr+LANCE_ADDR);
1788
1789 /* ----- start when init done. ----- */
1790 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1791 out_word(ioaddr+LANCE_DATA, 0x1); /* init */
1792 for (i = 10000; i > 0; --i)
1793 if (in_word(ioaddr+LANCE_DATA) & 0x100)
1794 break;
1795
1796 /* Set 'Multicast Table' */
1797 for (i=0;i<4;++i)
1798 {
1799 out_word(ioaddr+LANCE_ADDR, 0x8 + i);
1800 out_word(ioaddr+LANCE_DATA, 0xffff);
1801 }
1802
1803 /* Set 'Receive Mode' */
1804 if (ec->flags & ECF_PROMISC)
1805 {
1806 out_word(ioaddr+LANCE_ADDR, 0xf);
1807 out_word(ioaddr+LANCE_DATA, 0x8000);
1808 }
1809 else
1810 {
1811 if (ec->flags & (ECF_BROAD | ECF_MULTI))
1812 {
1813 out_word(ioaddr+LANCE_ADDR, 0xf);
1814 out_word(ioaddr+LANCE_DATA, 0x0000);
1815 }
1816 else
1817 {
1818 out_word(ioaddr+LANCE_ADDR, 0xf);
1819 out_word(ioaddr+LANCE_DATA, 0x4000);
1820 }
1821 }
1822
1823 out_word(ioaddr+LANCE_ADDR, 0x0);
1824 (void)in_word(ioaddr+LANCE_ADDR);
1825 out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */
1826
1827 return;
1828 }
Cache object: e756577cf1d7b849be81465697e72df2
|