1 /*
2 * lance.c
3 *
4 * This file contains a ethernet device driver for AMD LANCE based ethernet
5 * cards.
6 *
7 * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
8 * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
9 */
10
11 #define VERBOSE 0 /* Verbose debugging output */
12 #define LANCE_FKEY 0 /* Use function key to dump Lance stats */
13
14 #include <minix/drivers.h>
15 #include <minix/netdriver.h>
16
17 #include <assert.h>
18
19 #include <minix/syslib.h>
20 #include <minix/endpoint.h>
21 #include <machine/pci.h>
22 #include <minix/ds.h>
23
24 #include "lance.h"
25
26 static int do_init(unsigned int instance, netdriver_addr_t *addr,
27 uint32_t *caps, unsigned int *ticks);
28 static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance);
29 static void ec_reinit(ether_card_t *ec);
30 static void do_intr(unsigned int mask);
31 static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
32 unsigned int mcast_count);
33 static int do_send(struct netdriver_data *data, size_t size);
34 static ssize_t do_recv(struct netdriver_data *data, size_t max);
35 static void do_stop(void);
36 static void lance_dump(void);
37 static void do_other(const message *m_ptr, int ipc_status);
38 static void get_addressing(int devind, ether_card_t *ec);
39 static int lance_probe(ether_card_t *ec, unsigned int skip);
40 static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
41 unsigned int instance);
42
43 /* Accesses Lance Control and Status Registers */
44 static u8_t in_byte(port_t port);
45 static u16_t in_word(port_t port);
46 static void out_word(port_t port, u16_t value);
47 static u16_t read_csr(port_t ioaddr, u16_t csrno);
48 static void write_csr(port_t ioaddr, u16_t csrno, u16_t value);
49
50 static ether_card_t ec_state;
51
52 /* --- LANCE --- */
53 /* General */
54 typedef uint32_t Address;
55
56 #define ETH_FRAME_LEN 1518
57
58 #define LANCE_MUST_PAD 0x00000001
59 #define LANCE_ENABLE_AUTOSELECT 0x00000002
60 #define LANCE_SELECT_PHONELINE 0x00000004
61 #define LANCE_MUST_UNRESET 0x00000008
62
63 static const struct lance_chip_type
64 {
65 int id_number;
66 const char *name;
67 int flags;
68 } chip_table[] = {
69 {0x0000, "LANCE 7990", /* Ancient lance chip. */
70 LANCE_MUST_PAD + LANCE_MUST_UNRESET},
71 {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
72 LANCE_ENABLE_AUTOSELECT},
73 {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
74 LANCE_ENABLE_AUTOSELECT},
75 {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
76 LANCE_ENABLE_AUTOSELECT},
77 {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
78 LANCE_ENABLE_AUTOSELECT},
79 {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
80 LANCE_ENABLE_AUTOSELECT},
81 {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
82 LANCE_ENABLE_AUTOSELECT},
83 {0x2626, "PCnet/HomePNA 79C978",
84 LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
85 {0x0, "PCnet (unknown)",
86 LANCE_ENABLE_AUTOSELECT},
87 };
88
89 /* ############## for LANCE device ############## */
90 #define LANCE_ETH_ADDR 0x0
91 #define LANCE_DATA 0x10
92 #define LANCE_ADDR 0x12
93 #define LANCE_RESET 0x14
94 #define LANCE_BUS_IF 0x16
95 #define LANCE_TOTAL_SIZE 0x18
96
97 /* Use 2^4=16 {Rx,Tx} buffers */
98 #define LANCE_LOG_RX_BUFFERS 4
99 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
100 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
101 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
102
103 #define LANCE_LOG_TX_BUFFERS 4
104 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
105 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
106 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
107
108 /* for lance_interface */
109 struct lance_init_block
110 {
111 unsigned short mode;
112 unsigned char phys_addr[6];
113 unsigned long filter[2];
114 Address rx_ring;
115 Address tx_ring;
116 };
117
118 struct lance_rx_head
119 {
120 union {
121 Address base;
122 unsigned char addr[4];
123 } u;
124 short buf_length; /* 2s complement */
125 short msg_length;
126 };
127
128 struct lance_tx_head
129 {
130 union {
131 Address base;
132 unsigned char addr[4];
133 } u;
134 short buf_length; /* 2s complement */
135 short misc;
136 };
137
138 struct lance_interface
139 {
140 struct lance_init_block init_block;
141 struct lance_rx_head rx_ring[RX_RING_SIZE];
142 struct lance_tx_head tx_ring[TX_RING_SIZE];
143 unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN];
144 unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN];
145 };
146
147 /* =============== global variables =============== */
148 /* AKA the stuff that really should have been in ether_card_t */
149 static struct lance_interface *lp;
150 #define LANCE_BUF_SIZE (sizeof(struct lance_interface))
151 static char *lance_buf = NULL;
152 static int rx_slot_nr = 0; /* Rx-slot number */
153 static int tx_slot_nr = 0; /* Tx-slot number */
154 static int cur_tx_slot_nr = 0; /* Tx-slot number */
155 static phys_bytes tx_ring_base[TX_RING_SIZE]; /* Tx-slot physical address */
156 static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
157
158 static const struct netdriver lance_table = {
159 .ndr_name = "le",
160 .ndr_init = do_init,
161 .ndr_stop = do_stop,
162 .ndr_set_mode = do_set_mode,
163 .ndr_recv = do_recv,
164 .ndr_send = do_send,
165 .ndr_intr = do_intr,
166 .ndr_other = do_other,
167 };
168
169 /*===========================================================================*
170 * main *
171 *===========================================================================*/
main(int argc,char ** argv)172 int main(int argc, char **argv)
173 {
174
175 env_setargs(argc, argv);
176
177 netdriver_task(&lance_table);
178
179 return 0;
180 }
181
182 /*===========================================================================*
183 * lance_dump *
184 *===========================================================================*/
lance_dump()185 static void lance_dump()
186 {
187 ether_card_t *ec;
188 int isr, csr;
189 unsigned short ioaddr;
190
191 printf("\n");
192 ec = &ec_state;
193
194 printf("lance driver %s:\n", netdriver_name());
195
196 ioaddr = ec->ec_port;
197 isr = read_csr(ioaddr, LANCE_CSR0);
198 printf("isr = 0x%x, mode = 0x%x\n", isr, ec->ec_mode);
199
200 printf("irq = %d\tioadr = 0x%x\n", ec->ec_irq, ec->ec_port);
201
202 csr = read_csr(ioaddr, LANCE_CSR0);
203 printf("CSR0: 0x%x\n", csr);
204 csr = read_csr(ioaddr, LANCE_CSR3);
205 printf("CSR3: 0x%x\n", csr);
206 csr = read_csr(ioaddr, LANCE_CSR4);
207 printf("CSR4: 0x%x\n", csr);
208 csr = read_csr(ioaddr, LANCE_CSR5);
209 printf("CSR5: 0x%x\n", csr);
210 csr = read_csr(ioaddr, LANCE_CSR15);
211 printf("CSR15: 0x%x\n", csr);
212 }
213
214 /*===========================================================================*
215 * do_other *
216 *===========================================================================*/
do_other(const message * m_ptr,int ipc_status)217 static void do_other(const message *m_ptr, int ipc_status)
218 {
219
220 if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR)
221 lance_dump();
222 }
223
224 /*===========================================================================*
225 * ec_confaddr *
226 *===========================================================================*/
ec_confaddr(netdriver_addr_t * addr,unsigned int instance)227 static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance)
228 {
229 int i;
230 char eakey[16];
231 static char eafmt[]= "x:x:x:x:x:x";
232 long v;
233
234 /* User defined ethernet address? */
235 strlcpy(eakey, "LANCE0_EA", sizeof(eakey));
236 eakey[5] += instance;
237
238 for (i = 0; i < 6; i++)
239 {
240 v= addr->na_addr[i];
241 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
242 break;
243 addr->na_addr[i]= v;
244 }
245
246 if (i != 0 && i != 6)
247 {
248 /* It's all or nothing; force a panic. */
249 panic("invalid ethernet address supplied");
250 }
251 }
252
253 /*===========================================================================*
254 * do_init *
255 *===========================================================================*/
do_init(unsigned int instance,netdriver_addr_t * addr,uint32_t * caps,unsigned int * ticks __unused)256 static int do_init(unsigned int instance, netdriver_addr_t *addr,
257 uint32_t *caps, unsigned int *ticks __unused)
258 {
259 /* Initialize the lance driver. */
260 ether_card_t *ec;
261 #if VERBOSE
262 int i;
263 #endif
264 #if LANCE_FKEY
265 int r, fkeys, sfkeys;
266 #endif
267
268 #if LANCE_FKEY
269 fkeys = sfkeys = 0;
270 bit_set( sfkeys, 7 );
271 if ( (r = fkey_map(&fkeys, &sfkeys)) != OK )
272 printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r);
273 #endif
274
275 /* Initialize the driver state. */
276 ec= &ec_state;
277 memset(ec, 0, sizeof(*ec));
278
279 /* See if there is a matching card. */
280 if (!lance_probe(ec, instance))
281 return ENXIO;
282
283 /* Initialize the hardware. */
284 lance_init_hw(ec, addr, instance);
285
286 #if VERBOSE
287 printf("%s: Ethernet address ", netdriver_name());
288 for (i= 0; i < 6; i++)
289 printf("%x%c", addr->na_addr[i], i < 5 ? ':' : '\n');
290 #endif
291
292 *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
293 return OK;
294 }
295
296 /*===========================================================================*
297 * ec_reinit *
298 *===========================================================================*/
ec_reinit(ether_card_t * ec)299 static void ec_reinit(ether_card_t *ec)
300 {
301 spin_t spin;
302 int i;
303 unsigned short ioaddr = ec->ec_port;
304
305 /* stop */
306 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
307 /* init */
308 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_INIT);
309 /* poll for IDON */
310 SPIN_FOR(&spin, 1000) {
311 if (read_csr(ioaddr, LANCE_CSR0) & LANCE_CSR0_IDON)
312 break;
313 }
314
315 /* Set 'Multicast Table' */
316 for (i=0;i<4;++i)
317 {
318 write_csr(ioaddr, LANCE_CSR8 + i, 0xffff);
319 }
320
321 /* Set 'Receive Mode' */
322 if (ec->ec_mode & NDEV_MODE_PROMISC)
323 {
324 write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM);
325 }
326 else
327 {
328 if (ec->ec_mode &
329 (NDEV_MODE_BCAST | NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
330 {
331 write_csr(ioaddr, LANCE_CSR15, 0x0000);
332 }
333 else
334 {
335 write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_DRCVBC);
336 }
337 }
338
339 /* purge Tx-ring */
340 tx_slot_nr = cur_tx_slot_nr = 0;
341 for (i=0; i<TX_RING_SIZE; i++)
342 {
343 lp->tx_ring[i].u.base = 0;
344 isstored[i]=0;
345 }
346 cur_tx_slot_nr = tx_slot_nr;
347
348 /* re-init Rx-ring */
349 rx_slot_nr = 0;
350 for (i=0; i<RX_RING_SIZE; i++)
351 {
352 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
353 lp->rx_ring[i].u.addr[3] |= 0x80;
354 }
355
356 /* start && enable interrupt */
357 write_csr(ioaddr, LANCE_CSR0,
358 LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT);
359
360 return;
361 }
362
363 /*===========================================================================*
364 * do_set_mode *
365 *===========================================================================*/
do_set_mode(unsigned int mode,const netdriver_addr_t * mcast_list __unused,unsigned int mcast_count __unused)366 static void do_set_mode(unsigned int mode,
367 const netdriver_addr_t *mcast_list __unused,
368 unsigned int mcast_count __unused)
369 {
370 ether_card_t *ec;
371
372 ec = &ec_state;
373
374 ec->ec_mode = mode;
375
376 ec_reinit(ec);
377 }
378
379 /*===========================================================================*
380 * do_intr *
381 *===========================================================================*/
do_intr(unsigned int __unused mask)382 static void do_intr(unsigned int __unused mask)
383 {
384 ether_card_t *ec;
385 int must_restart = 0;
386 int r, check, status;
387 int isr = 0x0000;
388 unsigned short ioaddr;
389
390 ec = &ec_state;
391 ioaddr = ec->ec_port;
392
393 for (;;)
394 {
395 #if VERBOSE
396 printf("ETH: Reading ISR...");
397 #endif
398 isr = read_csr(ioaddr, LANCE_CSR0);
399 if (isr & (LANCE_CSR0_ERR|LANCE_CSR0_RINT|LANCE_CSR0_TINT)) {
400 write_csr(ioaddr, LANCE_CSR0,
401 isr & ~(LANCE_CSR0_IENA|LANCE_CSR0_TDMD|LANCE_CSR0_STOP
402 |LANCE_CSR0_STRT|LANCE_CSR0_INIT) );
403 }
404 write_csr(ioaddr, LANCE_CSR0,
405 LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS|LANCE_CSR0_MERR
406 |LANCE_CSR0_IDON|LANCE_CSR0_IENA);
407
408 if ((isr & (LANCE_CSR0_TINT|LANCE_CSR0_RINT|LANCE_CSR0_MISS
409 |LANCE_CSR0_BABL|LANCE_CSR0_ERR)) == 0x0000)
410 {
411 #if VERBOSE
412 printf("OK\n");
413 #endif
414 break;
415 }
416
417 if (isr & LANCE_CSR0_MISS)
418 {
419 #if VERBOSE
420 printf("RX Missed Frame\n");
421 #endif
422 netdriver_stat_ierror(1);
423 }
424 if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT))
425 {
426 if (isr & LANCE_CSR0_BABL)
427 {
428 #if VERBOSE
429 printf("TX Timeout\n");
430 #endif
431 netdriver_stat_oerror(1);
432 }
433 if (isr & LANCE_CSR0_TINT)
434 {
435 #if VERBOSE
436 printf("TX INT\n");
437 #endif
438 /* status check: restart if needed. */
439 status = lp->tx_ring[cur_tx_slot_nr].u.base;
440
441 /* did an error (UFLO, LCOL, LCAR, RTRY) occur? */
442 if (status & 0x40000000)
443 {
444 status = lp->tx_ring[cur_tx_slot_nr].misc;
445 netdriver_stat_oerror(1);
446 if (status & 0x4000) /* UFLO */
447 {
448 must_restart=1;
449 }
450 }
451 else
452 {
453 if (status & 0x18000000)
454 netdriver_stat_coll(1);
455 }
456 }
457 /* transmit a packet on the next slot if it exists. */
458 check = 0;
459 if (isstored[cur_tx_slot_nr]==1)
460 {
461 /* free the tx-slot just transmitted */
462 isstored[cur_tx_slot_nr]=0;
463 cur_tx_slot_nr = (cur_tx_slot_nr + 1) & TX_RING_MOD_MASK;
464
465 /* next tx-slot is ready? */
466 if (isstored[cur_tx_slot_nr]==1)
467 check=1;
468 else
469 check=0;
470 }
471 else
472 {
473 panic("got premature TX INT..");
474 }
475 if (check==1)
476 {
477 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
478 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD);
479 }
480 /* we set a buffered message in the slot if it exists. */
481 /* and transmit it, if needed. */
482 if (!must_restart)
483 netdriver_send();
484 }
485 if (isr & LANCE_CSR0_RINT)
486 {
487 #if VERBOSE
488 printf("RX INT\n");
489 #endif
490 netdriver_recv();
491 }
492
493 if (must_restart == 1)
494 {
495 #if VERBOSE
496 printf("ETH: restarting...\n");
497 #endif
498
499 ec_reinit(ec);
500
501 /* store a buffered message on the slot if it exists */
502 netdriver_send();
503 }
504 }
505
506 /* reenable interrupts */
507 if ((r = sys_irqenable(&ec->ec_hook)) != OK)
508 panic("couldn't enable interrupt: %d", r);
509 }
510
511 /*===========================================================================*
512 * do_recv *
513 *===========================================================================*/
do_recv(struct netdriver_data * data,size_t max)514 static ssize_t do_recv(struct netdriver_data *data, size_t max)
515 {
516 ether_card_t *ec;
517 vir_bytes length;
518 int packet_processed;
519 int status;
520 unsigned short ioaddr;
521
522 ec = &ec_state;
523 ioaddr = ec->ec_port;
524
525 /* we check all the received slots until find a properly received packet */
526 packet_processed = FALSE;
527 while (!packet_processed)
528 {
529 status = lp->rx_ring[rx_slot_nr].u.base >> 24;
530
531 /* is the slot marked as ready? */
532 if ( (status & 0x80) != 0x00 )
533 return SUSPEND; /* no */
534
535 /* did an error occur? */
536 if (status != 0x03)
537 {
538 if (status & 0x01)
539 netdriver_stat_ierror(1);
540 length = 0;
541 }
542 else
543 {
544 length = lp->rx_ring[rx_slot_nr].msg_length;
545 }
546
547 /* do we now have a valid packet? */
548 if (length > 0)
549 {
550 if (length > max)
551 length = max;
552 netdriver_copyout(data, 0, lp->rbuf[rx_slot_nr], length);
553 packet_processed = TRUE;
554 }
555
556 /* set up this slot again, and we move to the next slot */
557 lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;
558 lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;
559
560 write_csr(ioaddr, LANCE_CSR0,
561 LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS
562 |LANCE_CSR0_MERR|LANCE_CSR0_IDON|LANCE_CSR0_IENA);
563
564 rx_slot_nr = (rx_slot_nr + 1) & RX_RING_MOD_MASK;
565 }
566
567 /* return the length of the packet we have received */
568 return length;
569 }
570
571 /*===========================================================================*
572 * do_send *
573 *===========================================================================*/
do_send(struct netdriver_data * data,size_t size)574 static int do_send(struct netdriver_data *data, size_t size)
575 {
576 int check;
577 ether_card_t *ec;
578 unsigned short ioaddr;
579
580 ec = &ec_state;
581
582 /* if all slots are used, this request must be deferred */
583 if (isstored[tx_slot_nr]==1)
584 return SUSPEND;
585
586 /* copy the packet to the slot on DMA address */
587 netdriver_copyin(data, 0, lp->tbuf[tx_slot_nr], size);
588
589 /* set-up for transmitting, and transmit it if needed. */
590 lp->tx_ring[tx_slot_nr].buf_length = -size;
591 lp->tx_ring[tx_slot_nr].misc = 0x0;
592 lp->tx_ring[tx_slot_nr].u.base = tx_ring_base[tx_slot_nr];
593 isstored[tx_slot_nr]=1;
594 if (cur_tx_slot_nr == tx_slot_nr)
595 check=1;
596 else
597 check=0;
598 tx_slot_nr = (tx_slot_nr + 1) & TX_RING_MOD_MASK;
599
600 if (check == 1)
601 {
602 ioaddr = ec->ec_port;
603 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
604 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD);
605 }
606
607 return OK;
608 }
609
610 /*===========================================================================*
611 * do_stop *
612 *===========================================================================*/
do_stop(void)613 static void do_stop(void)
614 {
615 ether_card_t *ec;
616 unsigned short ioaddr;
617
618 ec = &ec_state;
619
620 ioaddr = ec->ec_port;
621
622 /* stop */
623 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
624
625 /* Reset */
626 in_word(ioaddr+LANCE_RESET);
627 }
628
629 /*===========================================================================*
630 * get_addressing *
631 *===========================================================================*/
get_addressing(int devind,ether_card_t * ec)632 static void get_addressing(int devind, ether_card_t *ec)
633 {
634 unsigned int ioaddr;
635 int reg, irq;
636
637 for (reg = PCI_BAR; reg <= PCI_BAR_6; reg += 4)
638 {
639 ioaddr = pci_attr_r32(devind, reg);
640
641 if ((ioaddr & PCI_BAR_IO_MASK) == 0 || (ioaddr & PCI_BAR_IO) == 0)
642 continue;
643 /* Strip the I/O address out of the returned value */
644 ioaddr &= PCI_BAR_IO_MASK;
645 ec->ec_port = ioaddr;
646 }
647
648 /* KK: Get the IRQ number */
649 irq = pci_attr_r8(devind, PCI_IPR);
650 if (irq)
651 irq = pci_attr_r8(devind, PCI_ILR);
652 ec->ec_irq = irq;
653 }
654
655 /*===========================================================================*
656 * lance_probe *
657 *===========================================================================*/
lance_probe(ether_card_t * ec,unsigned int skip)658 static int lance_probe(ether_card_t *ec, unsigned int skip)
659 {
660 unsigned short pci_cmd;
661 unsigned short ioaddr;
662 int lance_version, chip_version;
663 int devind, r;
664 u16_t vid, did;
665
666 pci_init();
667
668 r= pci_first_dev(&devind, &vid, &did);
669 if (r == 0)
670 return 0;
671
672 while (skip--)
673 {
674 r= pci_next_dev(&devind, &vid, &did);
675 if (!r)
676 return 0;
677 }
678
679 pci_reserve(devind);
680
681 get_addressing(devind, ec);
682
683 /* ===== Bus Master ? ===== */
684 pci_cmd = pci_attr_r32(devind, PCI_CR);
685 if (!(pci_cmd & PCI_CR_MAST_EN)) {
686 pci_cmd |= PCI_CR_MAST_EN;
687 pci_attr_w32(devind, PCI_CR, pci_cmd);
688 }
689
690 /* ===== Probe Details ===== */
691 ioaddr = ec->ec_port;
692
693 /* Reset */
694 in_word(ioaddr+LANCE_RESET);
695
696 if (read_csr(ioaddr, LANCE_CSR0) != LANCE_CSR0_STOP)
697 {
698 return 0;
699 }
700
701 /* Probe Chip Version */
702 out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */
703 if (in_word(ioaddr+LANCE_ADDR) != 88)
704 lance_version = 0;
705 else
706 {
707 chip_version = read_csr(ioaddr, LANCE_CSR88);
708 chip_version |= read_csr(ioaddr, LANCE_CSR89) << 16;
709
710 if ((chip_version & 0xfff) != 0x3)
711 {
712 return 0;
713 }
714 chip_version = (chip_version >> 12) & 0xffff;
715 for (lance_version = 1; chip_table[lance_version].id_number != 0;
716 ++lance_version)
717 if (chip_table[lance_version].id_number == chip_version)
718 break;
719 }
720
721 #if VERBOSE
722 printf("%s: %s at %X:%d\n",
723 netdriver_name(), chip_table[lance_version].name,
724 ec->ec_port, ec->ec_irq);
725 #endif
726
727 return lance_version;
728 }
729
730 /*===========================================================================*
731 * virt_to_bus *
732 *===========================================================================*/
virt_to_bus(void * ptr)733 static phys_bytes virt_to_bus(void *ptr)
734 {
735 phys_bytes value;
736 int r;
737
738 if ((r = sys_umap(SELF, VM_D, (vir_bytes)ptr, 4, &value)) != OK)
739 panic("sys_umap failed: %d", r);
740
741 return value;
742 }
743
744 /*===========================================================================*
745 * lance_init_hw *
746 *===========================================================================*/
lance_init_hw(ether_card_t * ec,netdriver_addr_t * addr,unsigned int instance)747 static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
748 unsigned int instance)
749 {
750 phys_bytes lance_buf_phys;
751 int i, r;
752 Address l;
753 unsigned short ioaddr = ec->ec_port;
754
755 /* ============= setup init_block(cf. lance_probe1) ================ */
756 /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
757
758 /* Allocate memory */
759 if ((lance_buf = alloc_contig(LANCE_BUF_SIZE, AC_ALIGN4K|AC_LOWER16M,
760 &lance_buf_phys)) == NULL)
761 panic("alloc_contig failed: %d", LANCE_BUF_SIZE);
762
763 l = (vir_bytes)lance_buf;
764 lp = (struct lance_interface *)l;
765
766 /* disable Tx and Rx */
767 lp->init_block.mode = LANCE_CSR15_DTX|LANCE_CSR15_DRX;
768 lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
769 /* using multiple Rx/Tx buffer */
770 lp->init_block.rx_ring
771 = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
772 lp->init_block.tx_ring
773 = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
774
775 l = virt_to_bus(&lp->init_block);
776 write_csr(ioaddr, LANCE_CSR1, (unsigned short)l);
777 write_csr(ioaddr, LANCE_CSR2, (unsigned short)(l >> 16));
778 write_csr(ioaddr, LANCE_CSR4,
779 LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM
780 |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM);
781
782 /* ============= Get MAC address (cf. lance_probe1) ================ */
783 for (i = 0; i < 6; ++i)
784 addr->na_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
785
786 /* Allow the user to override the hardware address. */
787 ec_confaddr(addr, instance);
788
789 /* ============ (re)start init_block(cf. lance_reset) =============== */
790 /* Reset the LANCE */
791 (void)in_word(ioaddr+LANCE_RESET);
792
793 /* ----- Re-initialize the LANCE ----- */
794 /* Set station address */
795 for (i = 0; i < 6; ++i)
796 lp->init_block.phys_addr[i] = addr->na_addr[i];
797 /* Preset the receive ring headers */
798 for (i=0; i<RX_RING_SIZE; i++)
799 {
800 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
801 /* OWN */
802 lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
803 /* we set the top byte as the very last thing */
804 lp->rx_ring[i].u.addr[3] = 0x80;
805 }
806 /* Preset the transmitting ring headers */
807 for (i=0; i<TX_RING_SIZE; i++)
808 {
809 lp->tx_ring[i].u.base = 0;
810 tx_ring_base[i] = virt_to_bus(lp->tbuf[i]) & 0xffffff;
811 isstored[i] = 0;
812 }
813 /* enable Rx and Tx */
814 lp->init_block.mode = 0x0;
815
816 l = (Address)virt_to_bus(&lp->init_block);
817 write_csr(ioaddr, LANCE_CSR1, (short)l);
818 write_csr(ioaddr, LANCE_CSR2, (short)(l >> 16));
819 write_csr(ioaddr, LANCE_CSR4,
820 LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM
821 |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM);
822
823 /* ----- start when init done. ----- */
824 ec_reinit(ec);
825
826 /* Set the interrupt handler */
827 ec->ec_hook = ec->ec_irq;
828 if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)
829 panic("couldn't set IRQ policy: %d", r);
830 if ((r = sys_irqenable(&ec->ec_hook)) != OK)
831 panic("couldn't enable interrupt: %d", r);
832
833 /* start && enable interrupt */
834 write_csr(ioaddr, LANCE_CSR0,
835 LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT);
836 }
837
838 /*===========================================================================*
839 * in_byte *
840 *===========================================================================*/
in_byte(port_t port)841 static u8_t in_byte(port_t port)
842 {
843 int r;
844 u32_t value;
845
846 r= sys_inb(port, &value);
847 if (r != OK)
848 panic("sys_inb failed: %d", r);
849 return value;
850 }
851
852 /*===========================================================================*
853 * in_word *
854 *===========================================================================*/
in_word(port_t port)855 static u16_t in_word(port_t port)
856 {
857 int r;
858 u32_t value;
859
860 r= sys_inw(port, &value);
861 if (r != OK)
862 panic("sys_inw failed: %d", r);
863 return value;
864 }
865
866
867 /*===========================================================================*
868 * out_word *
869 *===========================================================================*/
out_word(port_t port,u16_t value)870 static void out_word(port_t port, u16_t value)
871 {
872 int r;
873
874 r= sys_outw(port, value);
875 if (r != OK)
876 panic("sys_outw failed: %d", r);
877 }
878
879 /*===========================================================================*
880 * read_csr *
881 *===========================================================================*/
read_csr(port_t ioaddr,u16_t csrno)882 static u16_t read_csr(port_t ioaddr, u16_t csrno)
883 {
884 out_word(ioaddr+LANCE_ADDR, csrno);
885 return in_word(ioaddr+LANCE_DATA);
886 }
887
888 /*===========================================================================*
889 * write_csr *
890 *===========================================================================*/
write_csr(port_t ioaddr,u16_t csrno,u16_t value)891 static void write_csr(port_t ioaddr, u16_t csrno, u16_t value)
892 {
893 out_word(ioaddr+LANCE_ADDR, csrno);
894 out_word(ioaddr+LANCE_DATA, value);
895 }
896