1 /**************************************************************************
2 ETHERBOOT - BOOTP/TFTP Bootstrap Program
7 This code is based heavily on David Greenman's if_ed.c driver
9 Copyright (C) 1993-1994, David Greenman, Martin Renters.
10 This software may be used, modified, copied, distributed, and sold, in
11 both source and binary form provided that the above copyright and these
12 terms are retained. Under no circumstances are the authors responsible for
13 the proper functioning of this software, nor do the authors assume any
14 responsibility for damages incurred with its use.
16 Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
17 Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
18 3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
19 SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
20 3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
21 RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
22 parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
23 SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
24 based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
26 **************************************************************************/
28 #warning "ns8390.c is a horrendous mess and needs to be tidied up"
32 #include "etherboot.h"
41 static unsigned char eth_vendor, eth_flags;
43 static unsigned char eth_laar;
45 static unsigned short eth_nic_base, eth_asic_base;
46 static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
47 static Address eth_bmem, eth_rmem;
48 static unsigned char eth_drain_receiver;
51 static struct wd_board {
57 {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
58 {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
59 {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
60 {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
61 {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
62 {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
64 TYPE_WD8013EP, 0, MEM_8192},
65 {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
66 {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
67 {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
68 {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
69 {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
70 {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
71 {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
77 static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
80 #if defined(INCLUDE_WD)
81 #define ASIC_PIO WD_IAR
82 #define eth_probe wd_probe
83 #if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
84 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
88 #if defined(INCLUDE_3C503)
89 #define eth_probe t503_probe
90 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
91 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
95 #if defined(INCLUDE_NE)
96 #define eth_probe ne_probe
97 #if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
98 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
102 #if defined(INCLUDE_NS8390)
103 #define eth_probe nepci_probe
104 #if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
105 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
109 #if defined(INCLUDE_3C503)
110 #define ASIC_PIO _3COM_RFMSB
112 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
113 #define ASIC_PIO NE_DATA
117 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
118 /**************************************************************************
119 ETH_PIO_READ - Read a frame via Programmed I/O
120 **************************************************************************/
121 static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
124 outb(src & 0xff, eth_asic_base + WD_GP2);
125 outb(src >> 8, eth_asic_base + WD_GP2);
127 outb(D8390_COMMAND_RD2 |
128 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
129 outb(cnt, eth_nic_base + D8390_P0_RBCR0);
130 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
131 outb(src, eth_nic_base + D8390_P0_RSAR0);
132 outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
133 outb(D8390_COMMAND_RD0 |
134 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
137 outb(src & 0xff, eth_asic_base + _3COM_DALSB);
138 outb(src >> 8, eth_asic_base + _3COM_DAMSB);
139 outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
143 if (eth_flags & FLAG_16BIT)
144 cnt = (cnt + 1) >> 1;
148 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
152 if (eth_flags & FLAG_16BIT) {
153 *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
157 *(dst++) = inb(eth_asic_base + ASIC_PIO);
161 outb(t503_output, eth_asic_base + _3COM_CR);
165 /**************************************************************************
166 ETH_PIO_WRITE - Write a frame via Programmed I/O
167 **************************************************************************/
168 static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
170 #ifdef COMPEX_RL2000_FIX
172 #endif /* COMPEX_RL2000_FIX */
174 outb(dst & 0xff, eth_asic_base + WD_GP2);
175 outb(dst >> 8, eth_asic_base + WD_GP2);
177 outb(D8390_COMMAND_RD2 |
178 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
179 outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
180 outb(cnt, eth_nic_base + D8390_P0_RBCR0);
181 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
182 outb(dst, eth_nic_base + D8390_P0_RSAR0);
183 outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
184 outb(D8390_COMMAND_RD1 |
185 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
188 outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
189 outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
191 outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
195 if (eth_flags & FLAG_16BIT)
196 cnt = (cnt + 1) >> 1;
201 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
205 if (eth_flags & FLAG_16BIT) {
206 outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
210 outb(*(src++), eth_asic_base + ASIC_PIO);
214 outb(t503_output, eth_asic_base + _3COM_CR);
216 #ifdef COMPEX_RL2000_FIX
218 x < COMPEX_RL2000_TRIES &&
219 (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
222 if (x >= COMPEX_RL2000_TRIES)
223 printf("Warning: Compex RL2000 aborted wait!\n");
224 #endif /* COMPEX_RL2000_FIX */
226 while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
232 /**************************************************************************
233 ETH_PIO_READ - Dummy routine when NE2000 not compiled in
234 **************************************************************************/
235 static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
239 /**************************************************************************
240 enable_multycast - Enable Multicast
241 **************************************************************************/
242 static void enable_multicast(unsigned short eth_nic_base)
244 unsigned char mcfilter[8];
246 memset(mcfilter, 0xFF, 8);
247 outb(4, eth_nic_base+D8390_P0_RCR);
248 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
251 outb(mcfilter[i], eth_nic_base + 8 + i);
252 if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
253 printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
255 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
256 outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
259 /**************************************************************************
260 NS8390_RESET - Reset adapter
261 **************************************************************************/
262 static void ns8390_reset(struct nic *nic)
266 eth_drain_receiver = 0;
268 if (eth_flags & FLAG_790)
269 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
272 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
273 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
274 if (eth_flags & FLAG_16BIT)
275 outb(0x49, eth_nic_base+D8390_P0_DCR);
277 outb(0x48, eth_nic_base+D8390_P0_DCR);
278 outb(0, eth_nic_base+D8390_P0_RBCR0);
279 outb(0, eth_nic_base+D8390_P0_RBCR1);
280 outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
281 outb(2, eth_nic_base+D8390_P0_TCR);
282 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
283 outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
285 if (eth_flags & FLAG_790) {
287 outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
288 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
290 outb(0, eth_nic_base + 0x09);
294 outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
295 outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
296 outb(0xFF, eth_nic_base+D8390_P0_ISR);
297 outb(0, eth_nic_base+D8390_P0_IMR);
299 if (eth_flags & FLAG_790)
300 outb(D8390_COMMAND_PS1 |
301 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
304 outb(D8390_COMMAND_PS1 |
305 D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
306 for (i=0; i<ETH_ALEN; i++)
307 outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
308 for (i=0; i<ETH_ALEN; i++)
309 outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
310 outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
312 if (eth_flags & FLAG_790)
313 outb(D8390_COMMAND_PS0 |
314 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
317 outb(D8390_COMMAND_PS0 |
318 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
319 outb(0xFF, eth_nic_base+D8390_P0_ISR);
320 outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
321 outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
323 enable_multicast(eth_nic_base);
327 * No way to tell whether or not we're supposed to use
328 * the 3Com's transceiver unless the user tells us.
329 * 'flags' should have some compile time default value
330 * which can be changed from the command menu.
332 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
333 outb(t503_output, eth_asic_base + _3COM_CR);
337 static int ns8390_poll(struct nic *nic, int retrieve);
339 #ifndef INCLUDE_3C503
340 /**************************************************************************
341 ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
342 **************************************************************************/
343 static void eth_rx_overrun(struct nic *nic)
348 if (eth_flags & FLAG_790)
349 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
352 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
353 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
355 /* wait for at least 1.6ms - we wait one timer tick */
356 start_time = currticks();
357 while (currticks() - start_time <= 1)
360 outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
361 outb(0, eth_nic_base+D8390_P0_RBCR1);
364 * Linux driver checks for interrupted TX here. This is not necessary,
365 * because the transmit routine waits until the frame is sent.
368 /* enter loopback mode and restart NIC */
369 outb(2, eth_nic_base+D8390_P0_TCR);
371 if (eth_flags & FLAG_790)
372 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
375 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
376 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
378 /* clear the RX ring, acknowledge overrun interrupt */
379 eth_drain_receiver = 1;
380 while (ns8390_poll(nic, 1))
382 eth_drain_receiver = 0;
383 outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
385 /* leave loopback mode - no packets to be resent (see Linux driver) */
386 outb(0, eth_nic_base+D8390_P0_TCR);
388 #endif /* INCLUDE_3C503 */
390 /**************************************************************************
391 NS8390_TRANSMIT - Transmit a frame
392 **************************************************************************/
393 static void ns8390_transmit(
395 const char *d, /* Destination */
396 unsigned int t, /* Type */
397 unsigned int s, /* size */
398 const char *p) /* Packet */
400 #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
401 Address eth_vmem = bus_to_virt(eth_bmem);
404 if (!(eth_flags & FLAG_PIO)) {
405 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
406 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
407 *((char *)eth_vmem+12) = t>>8; /* type */
408 *((char *)eth_vmem+13) = t;
409 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
411 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
416 if (eth_flags & FLAG_16BIT) {
417 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
421 /* Memory interface */
422 if (eth_flags & FLAG_790) {
423 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
427 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
428 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
429 *((char *)eth_vmem+12) = t>>8; /* type */
430 *((char *)eth_vmem+13) = t;
431 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
433 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
434 if (eth_flags & FLAG_790) {
435 outb(0, eth_asic_base + WD_MSR);
443 #if defined(INCLUDE_3C503)
444 if (eth_flags & FLAG_PIO)
446 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
450 type = (t >> 8) | (t << 8);
451 eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);
452 eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
453 /* bcc generates worse code without (const+const) below */
454 eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
455 eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);
457 if (s < ETH_ZLEN) s = ETH_ZLEN;
460 #if defined(INCLUDE_3C503)
464 if (eth_flags & FLAG_16BIT) {
465 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
468 if (eth_flags & FLAG_790)
469 outb(D8390_COMMAND_PS0 |
470 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
473 outb(D8390_COMMAND_PS0 |
474 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
475 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
476 outb(s, eth_nic_base+D8390_P0_TBCR0);
477 outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
479 if (eth_flags & FLAG_790)
480 outb(D8390_COMMAND_PS0 |
481 D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
484 outb(D8390_COMMAND_PS0 |
485 D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
486 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
489 /**************************************************************************
490 NS8390_POLL - Wait for a frame
491 **************************************************************************/
492 static int ns8390_poll(struct nic *nic, int retrieve)
495 unsigned char rstat, curr, next;
496 unsigned short len, frag;
497 unsigned short pktoff;
499 struct ringbuffer pkthdr;
501 #ifndef INCLUDE_3C503
502 /* avoid infinite recursion: see eth_rx_overrun() */
503 if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
507 #endif /* INCLUDE_3C503 */
508 rstat = inb(eth_nic_base+D8390_P0_RSR);
509 if (!(rstat & D8390_RSTAT_PRX)) return(0);
510 next = inb(eth_nic_base+D8390_P0_BOUND)+1;
511 if (next >= eth_memsize) next = eth_rx_start;
512 outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
513 curr = inb(eth_nic_base+D8390_P1_CURR);
514 outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
515 if (curr >= eth_memsize) curr=eth_rx_start;
516 if (curr == next) return(0);
518 if ( ! retrieve ) return 1;
521 if (eth_flags & FLAG_16BIT) {
522 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
526 if (eth_flags & FLAG_790) {
527 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
534 if (eth_flags & FLAG_PIO)
535 eth_pio_read(pktoff, (char *)&pkthdr, 4);
537 memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
538 pktoff += sizeof(pkthdr);
539 /* incoming length includes FCS so must sub 4 */
540 len = pkthdr.len - 4;
541 if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
542 || len > ETH_FRAME_LEN) {
543 printf("Bogus packet, ignoring\n");
548 nic->packetlen = len; /* available to caller */
549 frag = (eth_memsize << 8) - pktoff;
550 if (len > frag) { /* We have a wrap-around */
551 /* read first part */
552 if (eth_flags & FLAG_PIO)
553 eth_pio_read(pktoff, p, frag);
555 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
556 pktoff = eth_rx_start << 8;
560 /* read second part */
561 if (eth_flags & FLAG_PIO)
562 eth_pio_read(pktoff, p, len);
564 memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
569 if (eth_flags & FLAG_790) {
570 outb(0, eth_asic_base + WD_MSR);
574 if (eth_flags & FLAG_16BIT) {
575 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
580 next = pkthdr.next; /* frame number of next packet */
581 if (next == eth_rx_start)
583 outb(next-1, eth_nic_base+D8390_P0_BOUND);
587 /**************************************************************************
588 NS8390_DISABLE - Turn off adapter
589 **************************************************************************/
590 static void ns8390_disable ( struct nic *nic ) {
591 /* reset and disable merge */
595 /**************************************************************************
596 NS8390_IRQ - Enable, Disable, or Force interrupts
597 **************************************************************************/
598 static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
610 /**************************************************************************
611 ETH_PROBE - Look for an adapter
612 **************************************************************************/
613 #ifdef INCLUDE_NS8390
614 static int eth_probe (struct dev *dev, struct pci_device *pci)
616 static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
619 struct nic *nic = (struct nic *)dev;
621 #ifdef INCLUDE_NS8390
622 unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
623 unsigned short *probe_addrs = pci_probe_addrs;
625 eth_vendor = VENDOR_NONE;
626 eth_drain_receiver = 0;
632 /******************************************************************
633 Search for WD/SMC cards
634 ******************************************************************/
635 struct wd_board *brd;
636 unsigned short chksum;
638 for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
639 eth_asic_base += 0x20) {
642 chksum += inb(eth_asic_base+i);
643 /* Extra checks to avoid soundcard */
644 if ((chksum & 0xFF) == 0xFF &&
645 inb(eth_asic_base+8) != 0xFF &&
646 inb(eth_asic_base+9) != 0xFF)
649 if (eth_asic_base > WD_HIGH_BASE)
651 /* We've found a board */
652 eth_vendor = VENDOR_WD;
653 eth_nic_base = eth_asic_base + WD_NIC_ADDR;
655 nic->ioaddr = eth_nic_base;
657 c = inb(eth_asic_base+WD_BID); /* Get board id */
658 for (brd = wd_boards; brd->name; brd++)
659 if (brd->id == c) break;
661 printf("Unknown WD/SMC NIC type %hhX\n", c);
662 return (0); /* Unknown type */
664 eth_flags = brd->flags;
665 eth_memsize = brd->memsize;
667 eth_rx_start = D8390_TXBUF_SIZE;
668 if ((c == TYPE_WD8013EP) &&
669 (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
670 eth_flags = FLAG_16BIT;
671 eth_memsize = MEM_16384;
673 if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
674 eth_bmem = (0x80000 |
675 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
677 eth_bmem = WD_DEFAULT_MEM;
678 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
679 /* from Linux driver, 8416BT detects as 8216 sometimes */
680 unsigned int addr = inb(eth_asic_base + 0xb);
681 if (((addr >> 4) & 3) == 0) {
683 eth_memsize = brd->memsize;
686 outb(0x80, eth_asic_base + WD_MSR); /* Reset */
687 for (i=0; i<ETH_ALEN; i++) {
688 nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
690 printf("\n%s base %#hx", brd->name, eth_asic_base);
691 if (eth_flags & FLAG_790) {
693 printf(", PIO mode, addr %!\n", nic->node_addr);
695 eth_flags |= FLAG_PIO; /* force PIO mode */
696 outb(0, eth_asic_base+WD_MSR);
698 printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr);
699 outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
700 outb((inb(eth_asic_base+0x04) |
701 0x80), eth_asic_base+0x04);
702 outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
703 ((unsigned)(eth_bmem >> 11) & 0x40) |
704 (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
705 outb((inb(eth_asic_base+0x04) &
706 ~0x80), eth_asic_base+0x04);
709 printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr);
710 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
712 if (eth_flags & FLAG_16BIT) {
713 if (eth_flags & FLAG_790) {
714 eth_laar = inb(eth_asic_base + WD_LAAR);
715 outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
718 WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
720 The previous line used to be
721 WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
722 jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
723 it work for WD8013s. This seems to work for my 8013 boards. I
724 don't know what is really happening. I wish I had data sheets
725 or more time to decode the Linux driver. - Ken
734 nic->flags = 1; /* aui */
736 nic->flags = 0; /* no aui */
738 /******************************************************************
739 Search for 3Com 3c503 if no WD/SMC cards
740 ******************************************************************/
741 if (eth_vendor == VENDOR_NONE) {
743 int iobase_reg, membase_reg;
744 static unsigned short base[] = {
745 0x300, 0x310, 0x330, 0x350,
746 0x250, 0x280, 0x2A0, 0x2E0, 0 };
748 /* Loop through possible addresses checking each one */
750 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
752 eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
754 * Note that we use the same settings for both 8 and 16 bit cards:
755 * both have an 8K bank of memory at page 1 while only the 16 bit
756 * cards have a bank at page 0.
758 eth_memsize = MEM_16384;
760 eth_rx_start = 32 + D8390_TXBUF_SIZE;
762 /* Check our base address. iobase and membase should */
763 /* both have a maximum of 1 bit set or be 0. */
765 iobase_reg = inb(eth_asic_base + _3COM_BCFR);
766 membase_reg = inb(eth_asic_base + _3COM_PCFR);
768 if ((iobase_reg & (iobase_reg - 1)) ||
769 (membase_reg & (membase_reg - 1)))
772 /* Now get the shared memory address */
776 switch (membase_reg) {
777 case _3COM_PCFR_DC000:
780 case _3COM_PCFR_D8000:
783 case _3COM_PCFR_CC000:
786 case _3COM_PCFR_C8000:
790 eth_flags |= FLAG_PIO;
799 if (base[idx] == 0) /* not found */
802 eth_flags |= FLAG_PIO; /* force PIO mode */
805 eth_vendor = VENDOR_3COM;
808 /* Need this to make ns8390_poll() happy. */
810 eth_rmem = eth_bmem - 0x2000;
812 /* Reset NIC and ASIC */
814 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
815 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
817 /* Get our ethernet address */
819 outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
820 nic->ioaddr = eth_nic_base;
821 printf("\n3Com 3c503 base %#hx, ", eth_nic_base);
822 if (eth_flags & FLAG_PIO)
825 printf("memory %#x", eth_bmem);
826 for (i=0; i<ETH_ALEN; i++) {
827 nic->node_addr[i] = inb(eth_nic_base+i);
829 printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr",
831 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
833 * Initialize GA configuration register. Set bank and enable shared
834 * mem. We always use bank 1. Disable interrupts.
836 outb(_3COM_GACFR_RSEL |
837 _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
839 outb(0xff, eth_asic_base + _3COM_VPTR2);
840 outb(0xff, eth_asic_base + _3COM_VPTR1);
841 outb(0x00, eth_asic_base + _3COM_VPTR0);
843 * Clear memory and verify that it worked (we use only 8K)
846 if (!(eth_flags & FLAG_PIO)) {
847 memset(bus_to_virt(eth_bmem), 0, 0x2000);
848 for(i = 0; i < 0x2000; ++i)
849 if (*((char *)(bus_to_virt(eth_bmem+i)))) {
850 printf ("Failed to clear 3c503 shared mem.\n");
855 * Initialize GA page/start/stop registers.
857 outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
858 outb(eth_memsize, eth_asic_base + _3COM_PSPR);
861 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
863 /******************************************************************
864 Search for NE1000/2000 if no WD/SMC or 3com cards
865 ******************************************************************/
867 if (eth_vendor == VENDOR_NONE) {
868 char romdata[16], testbuf[32];
870 static char test[] = "NE*000 memory";
871 static unsigned short base[] = {
876 /* if no addresses supplied, fall back on defaults */
877 if (probe_addrs == 0 || probe_addrs[0] == 0)
879 eth_bmem = 0; /* No shared memory */
880 for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
881 eth_flags = FLAG_PIO;
882 eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
883 eth_memsize = MEM_16384;
885 eth_rx_start = 32 + D8390_TXBUF_SIZE;
886 c = inb(eth_asic_base + NE_RESET);
887 outb(c, eth_asic_base + NE_RESET);
889 outb(D8390_COMMAND_STP |
890 D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
891 outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
892 outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
893 outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
894 outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
895 #ifdef NS8390_FORCE_16BIT
896 eth_flags |= FLAG_16BIT; /* force 16-bit mode */
899 eth_pio_write(test, 8192, sizeof(test));
900 eth_pio_read(8192, testbuf, sizeof(test));
901 if (!memcmp(test, testbuf, sizeof(test)))
903 eth_flags |= FLAG_16BIT;
904 eth_memsize = MEM_32768;
906 eth_rx_start = 64 + D8390_TXBUF_SIZE;
908 D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
909 outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
910 outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
911 eth_pio_write(test, 16384, sizeof(test));
912 eth_pio_read(16384, testbuf, sizeof(test));
913 if (!memcmp(testbuf, test, sizeof(test)))
916 if (eth_nic_base == 0)
918 if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
919 eth_flags |= FLAG_16BIT;
920 eth_vendor = VENDOR_NOVELL;
921 eth_pio_read(0, romdata, sizeof(romdata));
922 for (i=0; i<ETH_ALEN; i++) {
923 nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
925 nic->ioaddr = eth_nic_base;
926 printf("\nNE%c000 base %#hx, addr %!\n",
927 (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
932 if (eth_vendor == VENDOR_NONE)
934 if (eth_vendor != VENDOR_3COM)
937 static struct nic_operations ns8390_operations;
938 static struct nic_operations ns8390_operations = {
939 .connect = dummy_connect,
941 .transmit = ns8390_transmit,
943 .disable = ns8390_disable,
945 nic->nic_op = &ns8390_operations;
947 /* Based on PnP ISA map */
949 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
950 dev->devid.device_id = htons(0x812a);
953 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
954 dev->devid.device_id = htons(0x80f3);
957 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
958 dev->devid.device_id = htons(0x80d6);
964 struct isa_driver wd_driver __isa_driver = {
970 ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
974 struct isa_driver t503_driver __isa_driver = {
980 ISA_ROM("3c503","3Com503, Etherlink II[/16]");
984 struct isa_driver ne_driver __isa_driver = {
990 ISA_ROM("ne","NE1000/2000 and clones");
993 #ifdef INCLUDE_NS8390
994 static struct pci_id nepci_nics[] = {
995 /* A few NE2000 PCI clones, list not exhaustive */
996 PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029"),
997 PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528"),
998 PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI"), /* Winbond 86C940 / 89C940 */
999 PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F"), /* Winbond 89C940F */
1000 PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000"),
1001 PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2"),
1002 PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC"),
1003 PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232"),
1004 PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229"),
1005 PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34"),
1006 PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926"),
1009 PCI_DRIVER ( nepci_driver, "NE2000/PCI", nepci_nics, PCI_NO_CLASS );
1011 BOOT_DRIVER ( "NE2000/PCI", nepci_probe );
1013 #endif /* INCLUDE_NS8390 */