iPXE
ns8390.c
Go to the documentation of this file.
1/**************************************************************************
2ETHERBOOT - BOOTP/TFTP Bootstrap Program
3
4Author: Martin Renters
5 Date: May/94
6
7 This code is based heavily on David Greenman's if_ed.c driver
8
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.
15
16Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
17Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
183c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
19SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
203c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
21RX 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)
23SMC8416 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)
25
26**************************************************************************/
27
28FILE_LICENCE ( BSD2 );
29
30/* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
31
32#if 1
33
34#if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
35 !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
36 /* The driver named ns8390 is the PCI driver, often called
37 "PCI ne2000 clones". */
38# define INCLUDE_NS8390 1
39#endif
40
41#include "etherboot.h"
42#include "nic.h"
43#include "ns8390.h"
44#include <ipxe/ethernet.h>
45#ifdef INCLUDE_NS8390
46#include <ipxe/pci.h>
47#else
48#include <ipxe/isa.h>
49#endif
50
51static unsigned char eth_vendor, eth_flags;
52#ifdef INCLUDE_WD
53static unsigned char eth_laar;
54#endif
55static unsigned short eth_nic_base, eth_asic_base;
56static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
58static unsigned char eth_drain_receiver;
59
60#ifdef INCLUDE_WD
61static struct wd_board {
62 const char *name;
63 char id;
64 char flags;
65 char memsize;
66} wd_boards[] = {
67 {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
68 {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
69 {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
70 {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
71 {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
72 {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
73 {"WD8003EP/WD8013EP",
75 {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
76 {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
79 {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
80 {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
81 {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
82 {NULL, 0, 0, 0}
83};
84#endif
85
86#ifdef INCLUDE_3C503
87static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
88#endif
89
90#if defined(INCLUDE_WD)
91#define ASIC_PIO WD_IAR
92#define eth_probe wd_probe
93#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
94Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
95#endif
96#endif
97
98#if defined(INCLUDE_3C503)
99#define eth_probe t503_probe
100#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
101Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
102#endif
103#endif
104
105#if defined(INCLUDE_NE)
106#define eth_probe ne_probe
107#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
108Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
109#endif
110#endif
111
112#if defined(INCLUDE_NS8390)
113#define eth_probe nepci_probe
114#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
115Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
116#endif
117#endif
118
119#if defined(INCLUDE_3C503)
120#define ASIC_PIO _3COM_RFMSB
121#else
122#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
123#define ASIC_PIO NE_DATA
124#endif
125#endif
126
127#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
128/**************************************************************************
129ETH_PIO_READ - Read a frame via Programmed I/O
130**************************************************************************/
131static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
132{
133#ifdef INCLUDE_WD
134 outb(src & 0xff, eth_asic_base + WD_GP2);
135 outb(src >> 8, eth_asic_base + WD_GP2);
136#else
145
146#ifdef INCLUDE_3C503
149 outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
150#endif
151#endif
152
153 if (eth_flags & FLAG_16BIT)
154 cnt = (cnt + 1) >> 1;
155
156 while(cnt--) {
157#ifdef INCLUDE_3C503
159 ;
160#endif
161
162 if (eth_flags & FLAG_16BIT) {
163 *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
164 dst += 2;
165 }
166 else
167 *(dst++) = inb(eth_asic_base + ASIC_PIO);
168 }
169
170#ifdef INCLUDE_3C503
171 outb(t503_output, eth_asic_base + _3COM_CR);
172#endif
173}
174
175/**************************************************************************
176ETH_PIO_WRITE - Write a frame via Programmed I/O
177**************************************************************************/
178static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
179{
180#ifdef COMPEX_RL2000_FIX
181 unsigned int x;
182#endif /* COMPEX_RL2000_FIX */
183#ifdef INCLUDE_WD
184 outb(dst & 0xff, eth_asic_base + WD_GP2);
185 outb(dst >> 8, eth_asic_base + WD_GP2);
186#else
196
197#ifdef INCLUDE_3C503
198 outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
199 outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
200
202#endif
203#endif
204
205 if (eth_flags & FLAG_16BIT)
206 cnt = (cnt + 1) >> 1;
207
208 while(cnt--)
209 {
210#ifdef INCLUDE_3C503
212 ;
213#endif
214
215 if (eth_flags & FLAG_16BIT) {
216 outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
217 src += 2;
218 }
219 else
221 }
222
223#ifdef INCLUDE_3C503
224 outb(t503_output, eth_asic_base + _3COM_CR);
225#else
226#ifdef COMPEX_RL2000_FIX
227 for (x = 0;
230 != D8390_ISR_RDC;
231 ++x);
232 if (x >= COMPEX_RL2000_TRIES)
233 printf("Warning: Compex RL2000 aborted wait!\n");
234#endif /* COMPEX_RL2000_FIX */
235#ifndef INCLUDE_WD
237 != D8390_ISR_RDC);
238#endif
239#endif
240}
241#else
242/**************************************************************************
243ETH_PIO_READ - Dummy routine when NE2000 not compiled in
244**************************************************************************/
245static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
246#endif
247
248
249/**************************************************************************
250enable_multycast - Enable Multicast
251**************************************************************************/
252static void enable_multicast(unsigned short eth_nic_base)
253{
254 unsigned char mcfilter[8];
255 int i;
256 memset(mcfilter, 0xFF, 8);
259 for(i=0;i<8;i++)
260 {
261 outb(mcfilter[i], eth_nic_base + 8 + i);
262 if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
263 printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
264 }
266 outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
267}
268
269/**************************************************************************
270NS8390_RESET - Reset adapter
271**************************************************************************/
272static void ns8390_reset(struct nic *nic)
273{
274 int i;
275
277#ifdef INCLUDE_WD
278 if (eth_flags & FLAG_790)
280 else
281#endif
284 if (eth_flags & FLAG_16BIT)
286 else
290 outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
294#ifdef INCLUDE_WD
295 if (eth_flags & FLAG_790) {
296#ifdef WD_790_PIO
297 outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
298 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
299#else
300 outb(0, eth_nic_base + 0x09);
301#endif
302 }
303#endif
308#ifdef INCLUDE_WD
309 if (eth_flags & FLAG_790)
312 else
313#endif
316 for (i=0; i<ETH_ALEN; i++)
318 for (i=0; i<ETH_ALEN; i++)
321#ifdef INCLUDE_WD
322 if (eth_flags & FLAG_790)
325 else
326#endif
330 outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
331 outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
332
334
335#ifdef INCLUDE_3C503
336 /*
337 * No way to tell whether or not we're supposed to use
338 * the 3Com's transceiver unless the user tells us.
339 * 'flags' should have some compile time default value
340 * which can be changed from the command menu.
341 */
342 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
343 outb(t503_output, eth_asic_base + _3COM_CR);
344#endif
345}
346
347static int ns8390_poll(struct nic *nic, int retrieve);
348
349#ifndef INCLUDE_3C503
350/**************************************************************************
351ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
352**************************************************************************/
353static void eth_rx_overrun(struct nic *nic)
354{
355 int start_time;
356
357#ifdef INCLUDE_WD
358 if (eth_flags & FLAG_790)
360 else
361#endif
364
365 /* wait for at least 1.6ms - we wait one timer tick */
366 start_time = currticks();
367 while (currticks() - start_time <= 1)
368 /* Nothing */;
369
370 outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
372
373 /*
374 * Linux driver checks for interrupted TX here. This is not necessary,
375 * because the transmit routine waits until the frame is sent.
376 */
377
378 /* enter loopback mode and restart NIC */
380#ifdef INCLUDE_WD
381 if (eth_flags & FLAG_790)
383 else
384#endif
387
388 /* clear the RX ring, acknowledge overrun interrupt */
390 while (ns8390_poll(nic, 1))
391 /* Nothing */;
394
395 /* leave loopback mode - no packets to be resent (see Linux driver) */
397}
398#endif /* INCLUDE_3C503 */
399
400/**************************************************************************
401NS8390_TRANSMIT - Transmit a frame
402**************************************************************************/
403static void ns8390_transmit(
404 struct nic *nic,
405 const char *d, /* Destination */
406 unsigned int t, /* Type */
407 unsigned int s, /* size */
408 const char *p) /* Packet */
409{
410#if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
411 Address eth_vmem = bus_to_virt(eth_bmem);
412#endif
413#ifdef INCLUDE_3C503
414 if (!(eth_flags & FLAG_PIO)) {
415 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
416 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
417 *((char *)eth_vmem+12) = t>>8; /* type */
418 *((char *)eth_vmem+13) = t;
419 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
420 s += ETH_HLEN;
421 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
422 }
423#endif
424
425#ifdef INCLUDE_WD
426 if (eth_flags & FLAG_16BIT) {
428 inb(0x84);
429 }
430#ifndef WD_790_PIO
431 /* Memory interface */
432 if (eth_flags & FLAG_790) {
434 inb(0x84);
435 }
436 inb(0x84);
437 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
438 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
439 *((char *)eth_vmem+12) = t>>8; /* type */
440 *((char *)eth_vmem+13) = t;
441 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
442 s += ETH_HLEN;
443 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
444 if (eth_flags & FLAG_790) {
446 inb(0x84);
447 }
448#else
449 inb(0x84);
450#endif
451#endif
452
453#if defined(INCLUDE_3C503)
454 if (eth_flags & FLAG_PIO)
455#endif
456#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
457 {
458 /* Programmed I/O */
459 unsigned short type;
460 type = (t >> 8) | (t << 8);
461 eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
463 /* bcc generates worse code without (const+const) below */
464 eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
465 eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
466 s += ETH_HLEN;
467 if (s < ETH_ZLEN) s = ETH_ZLEN;
468 }
469#endif
470#if defined(INCLUDE_3C503)
471#endif
472
473#ifdef INCLUDE_WD
474 if (eth_flags & FLAG_16BIT) {
475 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
476 inb(0x84);
477 }
478 if (eth_flags & FLAG_790)
481 else
482#endif
488#ifdef INCLUDE_WD
489 if (eth_flags & FLAG_790)
492 else
493#endif
497}
498
499/**************************************************************************
500NS8390_POLL - Wait for a frame
501**************************************************************************/
502static int ns8390_poll(struct nic *nic, int retrieve)
503{
504 int ret = 0;
505 unsigned char rstat, curr, next;
506 unsigned short len, frag;
507 unsigned short pktoff;
508 unsigned char *p;
509 struct ringbuffer pkthdr;
510
511#ifndef INCLUDE_3C503
512 /* avoid infinite recursion: see eth_rx_overrun() */
515 return(0);
516 }
517#endif /* INCLUDE_3C503 */
519 if (!(rstat & D8390_RSTAT_PRX)) return(0);
525 if (curr >= eth_memsize) curr=eth_rx_start;
526 if (curr == next) return(0);
527
528 if ( ! retrieve ) return 1;
529
530#ifdef INCLUDE_WD
531 if (eth_flags & FLAG_16BIT) {
533 inb(0x84);
534 }
535#ifndef WD_790_PIO
536 if (eth_flags & FLAG_790) {
538 inb(0x84);
539 }
540#endif
541 inb(0x84);
542#endif
543 pktoff = next << 8;
544 if (eth_flags & FLAG_PIO)
545 eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
546 else
547 memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
548 pktoff += sizeof(pkthdr);
549 /* incoming length includes FCS so must sub 4 */
550 len = pkthdr.len - 4;
551 if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
552 || len > ETH_FRAME_LEN) {
553 printf("Bogus packet, ignoring\n");
554 return (0);
555 }
556 else {
557 p = nic->packet;
558 nic->packetlen = len; /* available to caller */
559 frag = (eth_memsize << 8) - pktoff;
560 if (len > frag) { /* We have a wrap-around */
561 /* read first part */
562 if (eth_flags & FLAG_PIO)
563 eth_pio_read(pktoff, p, frag);
564 else
565 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
566 pktoff = eth_rx_start << 8;
567 p += frag;
568 len -= frag;
569 }
570 /* read second part */
571 if (eth_flags & FLAG_PIO)
572 eth_pio_read(pktoff, p, len);
573 else
574 memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
575 ret = 1;
576 }
577#ifdef INCLUDE_WD
578#ifndef WD_790_PIO
579 if (eth_flags & FLAG_790) {
581 inb(0x84);
582 }
583#endif
584 if (eth_flags & FLAG_16BIT) {
585 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
586 inb(0x84);
587 }
588 inb(0x84);
589#endif
590 next = pkthdr.next; /* frame number of next packet */
591 if (next == eth_rx_start)
594 return(ret);
595}
596
597/**************************************************************************
598NS8390_DISABLE - Turn off adapter
599**************************************************************************/
600static void ns8390_disable ( struct nic *nic, void *hwdev __unused ) {
602}
603
604/**************************************************************************
605NS8390_IRQ - Enable, Disable, or Force interrupts
606**************************************************************************/
607static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
608{
609 switch ( action ) {
610 case DISABLE :
611 break;
612 case ENABLE :
613 break;
614 case FORCE :
615 break;
616 }
617}
618
620static struct nic_operations ns8390_operations = {
621 .connect = dummy_connect,
622 .poll = ns8390_poll,
623 .transmit = ns8390_transmit,
624 .irq = ns8390_irq,
625};
626
627/**************************************************************************
628ETH_PROBE - Look for an adapter
629**************************************************************************/
630#ifdef INCLUDE_NS8390
631static int eth_probe (struct nic *nic, struct pci_device *pci)
632#else
633static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
634#endif
635{
636 int i;
637#ifdef INCLUDE_NS8390
638 unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
639 unsigned short *probe_addrs = pci_probe_addrs;
640#endif
643
644 nic->irqno = 0;
645
646#ifdef INCLUDE_WD
647{
648 /******************************************************************
649 Search for WD/SMC cards
650 ******************************************************************/
651 struct wd_board *brd;
652 unsigned short chksum;
653 unsigned char c;
655 eth_asic_base += 0x20) {
656 chksum = 0;
657 for (i=8; i<16; i++)
658 chksum += inb(eth_asic_base+i);
659 /* Extra checks to avoid soundcard */
660 if ((chksum & 0xFF) == 0xFF &&
661 inb(eth_asic_base+8) != 0xFF &&
662 inb(eth_asic_base+9) != 0xFF)
663 break;
664 }
666 return (0);
667 /* We've found a board */
670
672
673 c = inb(eth_asic_base+WD_BID); /* Get board id */
674 for (brd = wd_boards; brd->name; brd++)
675 if (brd->id == c) break;
676 if (!brd->name) {
677 printf("Unknown WD/SMC NIC type %hhX\n", c);
678 return (0); /* Unknown type */
679 }
680 eth_flags = brd->flags;
681 eth_memsize = brd->memsize;
682 eth_tx_start = 0;
684 if ((c == TYPE_WD8013EP) &&
688 }
689 if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
690 eth_bmem = (0x80000 |
691 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
692 } else
694 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
695 /* from Linux driver, 8416BT detects as 8216 sometimes */
696 unsigned int addr = inb(eth_asic_base + 0xb);
697 if (((addr >> 4) & 3) == 0) {
698 brd += 2;
699 eth_memsize = brd->memsize;
700 }
701 }
702 outb(0x80, eth_asic_base + WD_MSR); /* Reset */
703 for (i=0; i<ETH_ALEN; i++) {
705 }
706 DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
707 if (eth_flags & FLAG_790) {
708#ifdef WD_790_PIO
709 DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
710 eth_bmem = 0;
711 eth_flags |= FLAG_PIO; /* force PIO mode */
713#else
714 DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
715
717 outb((inb(eth_asic_base+0x04) |
718 0x80), eth_asic_base+0x04);
719 outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
720 ((unsigned)(eth_bmem >> 11) & 0x40) |
721 (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
722 outb((inb(eth_asic_base+0x04) &
723 ~0x80), eth_asic_base+0x04);
724#endif
725 } else {
726
727 DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
728
729 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
730 }
731 if (eth_flags & FLAG_16BIT) {
732 if (eth_flags & FLAG_790) {
733 eth_laar = inb(eth_asic_base + WD_LAAR);
735 } else {
736 outb((eth_laar =
738/*
739 The previous line used to be
740 WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
741 jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
742 it work for WD8013s. This seems to work for my 8013 boards. I
743 don't know what is really happening. I wish I had data sheets
744 or more time to decode the Linux driver. - Ken
745*/
746 }
747 inb(0x84);
748 }
749}
750#endif
751#ifdef INCLUDE_3C503
752#ifdef T503_AUI
753 nic->flags = 1; /* aui */
754#else
755 nic->flags = 0; /* no aui */
756#endif
757 /******************************************************************
758 Search for 3Com 3c503 if no WD/SMC cards
759 ******************************************************************/
760 if (eth_vendor == VENDOR_NONE) {
761 int idx;
762 int iobase_reg, membase_reg;
763 static unsigned short base[] = {
764 0x300, 0x310, 0x330, 0x350,
765 0x250, 0x280, 0x2A0, 0x2E0, 0 };
766
767 /* Loop through possible addresses checking each one */
768
769 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
770
772/*
773 * Note that we use the same settings for both 8 and 16 bit cards:
774 * both have an 8K bank of memory at page 1 while only the 16 bit
775 * cards have a bank at page 0.
776 */
778 eth_tx_start = 32;
780
781 /* Check our base address. iobase and membase should */
782 /* both have a maximum of 1 bit set or be 0. */
783
784 iobase_reg = inb(eth_asic_base + _3COM_BCFR);
785 membase_reg = inb(eth_asic_base + _3COM_PCFR);
786
787 if ((iobase_reg & (iobase_reg - 1)) ||
788 (membase_reg & (membase_reg - 1)))
789 continue; /* nope */
790
791 /* Now get the shared memory address */
792
793 eth_flags = 0;
794
795 switch (membase_reg) {
796 case _3COM_PCFR_DC000:
797 eth_bmem = 0xdc000;
798 break;
799 case _3COM_PCFR_D8000:
800 eth_bmem = 0xd8000;
801 break;
802 case _3COM_PCFR_CC000:
803 eth_bmem = 0xcc000;
804 break;
805 case _3COM_PCFR_C8000:
806 eth_bmem = 0xc8000;
807 break;
808 case _3COM_PCFR_PIO:
810 eth_bmem = 0;
811 break;
812 default:
813 continue; /* nope */
814 }
815 break;
816 }
817
818 if (base[idx] == 0) /* not found */
819 return (0);
820#ifndef T503_SHMEM
821 eth_flags |= FLAG_PIO; /* force PIO mode */
822 eth_bmem = 0;
823#endif
825
826
827 /* Need this to make ns8390_poll() happy. */
828
829 eth_rmem = eth_bmem - 0x2000;
830
831 /* Reset NIC and ASIC */
832
835
836 /* Get our ethernet address */
837
840 DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
841 if (eth_flags & FLAG_PIO)
842 DBG ( "PIO mode" );
843 else
844 DBG ( "memory %4.4x", eth_bmem );
845 for (i=0; i<ETH_ALEN; i++) {
846 nic->node_addr[i] = inb(eth_nic_base+i);
847 }
848 DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
849 eth_ntoa ( nic->node_addr ) );
850
852 /*
853 * Initialize GA configuration register. Set bank and enable shared
854 * mem. We always use bank 1. Disable interrupts.
855 */
858
862 /*
863 * Clear memory and verify that it worked (we use only 8K)
864 */
865
866 if (!(eth_flags & FLAG_PIO)) {
867 memset(bus_to_virt(eth_bmem), 0, 0x2000);
868 for(i = 0; i < 0x2000; ++i)
869 if (*((char *)(bus_to_virt(eth_bmem+i)))) {
870 printf ("Failed to clear 3c503 shared mem.\n");
871 return (0);
872 }
873 }
874 /*
875 * Initialize GA page/start/stop registers.
876 */
879 }
880#endif
881#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
882{
883 /******************************************************************
884 Search for NE1000/2000 if no WD/SMC or 3com cards
885 ******************************************************************/
886 unsigned char c;
887 if (eth_vendor == VENDOR_NONE) {
888 unsigned char romdata[16];
889 unsigned char testbuf[32];
890 int idx;
891 static unsigned char test[] = "NE*000 memory";
892 static unsigned short base[] = {
893#ifdef NE_SCAN
894 NE_SCAN,
895#endif
896 0 };
897 /* if no addresses supplied, fall back on defaults */
898 if (probe_addrs == NULL || probe_addrs[0] == 0)
899 probe_addrs = base;
900 eth_bmem = 0; /* No shared memory */
901 for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
905 eth_tx_start = 32;
909 (void) inb(0x84);
916#ifdef NS8390_FORCE_16BIT
917 eth_flags |= FLAG_16BIT; /* force 16-bit mode */
918#endif
919
920 eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
921 eth_pio_read(8192, testbuf, sizeof(test));
922 if (!memcmp(test, testbuf, sizeof(test)))
923 break;
926 eth_tx_start = 64;
932 eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
933 eth_pio_read(16384, testbuf, sizeof(test));
934 if (!memcmp(testbuf, test, sizeof(test)))
935 break;
936 }
937 if (eth_nic_base == 0)
938 return (0);
939 if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
942 eth_pio_read(0, romdata, sizeof(romdata));
943 for (i=0; i<ETH_ALEN; i++) {
944 nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
945 }
947 DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
948 (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
949 eth_ntoa ( nic->node_addr ) );
950 }
951}
952#endif
953 if (eth_vendor == VENDOR_NONE)
954 return(0);
955 if (eth_vendor != VENDOR_3COM)
959
960 /* Based on PnP ISA map */
961#ifdef INCLUDE_WD
962 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
963 dev->devid.device_id = htons(0x812a);
964#endif
965#ifdef INCLUDE_3C503
966 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
967 dev->devid.device_id = htons(0x80f3);
968#endif
969#ifdef INCLUDE_NE
970 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
971 dev->devid.device_id = htons(0x80d6);
972#endif
973 return 1;
974}
975
976#ifdef INCLUDE_WD
977struct isa_driver wd_driver __isa_driver = {
978 .type = NIC_DRIVER,
979 .name = "WD",
980 .probe = wd_probe,
981 .ioaddrs = 0,
982};
983ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
984#endif
985
986#ifdef INCLUDE_3C503
987struct isa_driver t503_driver __isa_driver = {
988 .type = NIC_DRIVER,
989 .name = "3C503",
990 .probe = t503_probe,
991 .ioaddrs = 0,
992};
993ISA_ROM("3c503","3Com503, Etherlink II[/16]");
994#endif
995
996#ifdef INCLUDE_NE
997struct isa_driver ne_driver __isa_driver = {
998 .type = NIC_DRIVER,
999 .name = "NE*000",
1000 .probe = ne_probe,
1001 .ioaddrs = 0,
1002};
1003ISA_ROM("ne","NE1000/2000 and clones");
1004#endif
1005
1006#ifdef INCLUDE_NS8390
1007static struct pci_device_id nepci_nics[] = {
1008/* A few NE2000 PCI clones, list not exhaustive */
1009PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0), /* Winbond 86C940 / 89C940 */
1010PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0), /* Winbond 89C940F */
1011PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
1012PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
1013PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
1014PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
1015PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
1016PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
1017PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
1018PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
1019PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
1020};
1021
1022PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
1023
1024DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
1025 nepci_probe, ns8390_disable, no_fake_bss );
1026
1027#endif /* INCLUDE_NS8390 */
1028
1029#endif
1030
1031/*
1032 * Local variables:
1033 * c-basic-offset: 8
1034 * c-indent-level: 8
1035 * tab-width: 8
1036 * End:
1037 */
static unsigned short eth_nic_base
Definition 3c595.c:38
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
static const void * src
Definition string.h:48
const char * name
Definition ath9k_hw.c:1986
uint32_t next
Next descriptor address.
Definition dwmac.h:11
ring len
Length.
Definition dwmac.h:226
uint32_t addr
Buffer address.
Definition dwmac.h:9
uint8_t id
Request identifier.
Definition ena.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t flags
Flags.
Definition ena.h:7
static int test
Definition epic100.c:73
unsigned long Address
Definition etherboot.h:21
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
Ethernet protocol.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETH_ZLEN
Definition if_ether.h:11
#define ETH_FRAME_LEN
Definition if_ether.h:12
#define ETH_ALEN
Definition if_ether.h:9
#define ETH_HLEN
Definition if_ether.h:10
#define htons(value)
Definition byteswap.h:136
#define inw(io_addr)
Definition io.h:292
#define outb(data, io_addr)
Definition io.h:310
static __always_inline void * bus_to_virt(unsigned long bus_addr)
Convert bus address to a virtual address.
Definition io.h:196
#define outw(data, io_addr)
Definition io.h:320
#define inb(io_addr)
Definition io.h:283
#define __isa_driver
Declare an ISA driver.
Definition isa.h:65
#define ISA_ROM(IMAGE, DESCRIPTION)
Definition isa.h:92
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define GENERIC_ISAPNP_VENDOR
Definition isa_ids.h:38
int dummy_connect(struct nic *nic __unused)
Definition legacy.c:175
uint32_t base
Base.
Definition librm.h:3
static unsigned char eth_drain_receiver
Definition ne2k_isa.c:37
static Address eth_rmem
Definition ne2k_isa.c:36
static Address eth_bmem
Definition ne2k_isa.c:36
static unsigned char eth_vendor
Definition ne2k_isa.c:33
#define ASIC_PIO
Definition ne2k_isa.c:31
static int ne_probe(struct nic *nic, struct isa_device *isa)
Definition ne2k_isa.c:135
static unsigned char eth_tx_start
Definition ne2k_isa.c:35
static unsigned short eth_asic_base
Definition ne2k_isa.c:34
static unsigned char eth_rx_start
Definition ne2k_isa.c:35
static unsigned char eth_flags
Definition ne2k_isa.c:33
static unsigned char eth_memsize
Definition ne2k_isa.c:35
#define DRIVER(_name_text, _unused2, _unused3, _name, _probe, _disable, _fake_bss)
Definition nic.h:220
irq_action_t
Definition nic.h:34
@ FORCE
Definition nic.h:37
@ ENABLE
Definition nic.h:36
@ DISABLE
Definition nic.h:35
#define PCI_DRIVER(_name, _ids, _class)
Definition nic.h:105
struct @002057171240057303273132130141036221271355330106 no_fake_bss
static void enable_multicast(unsigned short eth_nic_base)
Definition ns8390.c:252
static int ns8390_poll(struct nic *nic, int retrieve)
Definition ns8390.c:502
static void ns8390_reset(struct nic *nic)
Definition ns8390.c:272
static struct pci_device_id nepci_nics[]
Definition ns8390.c:1007
static void eth_rx_overrun(struct nic *nic)
Definition ns8390.c:353
static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
Definition ns8390.c:178
static struct nic_operations ns8390_operations
Definition ns8390.c:619
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
Definition ns8390.c:131
static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
Definition ns8390.c:607
#define eth_probe
Definition ns8390.c:113
static void ns8390_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
Definition ns8390.c:403
#define INCLUDE_NS8390
Definition ns8390.c:38
static void ns8390_disable(struct nic *nic, void *hwdev __unused)
Definition ns8390.c:600
#define WD_LAAR
Definition ns8390.h:44
#define WD_ICR_16BIT
Definition ns8390.h:50
#define VENDOR_NONE
Definition ns8390.h:11
#define D8390_P0_PSTOP
Definition ns8390.h:170
#define VENDOR_NOVELL
Definition ns8390.h:13
#define WD_HIGH_BASE
Definition ns8390.h:30
#define WD_ICR
Definition ns8390.h:40
#define D8390_P0_BOUND
Definition ns8390.h:171
#define TYPE_WD8013WC
Definition ns8390.h:69
#define D8390_RSTAT_PRX
Definition ns8390.h:221
#define NE_ASIC_OFFSET
Definition ns8390.h:159
#define D8390_COMMAND_STA
Definition ns8390.h:203
#define TYPE_WD8013W
Definition ns8390.h:67
#define COMPEX_RL2000_TRIES
Definition ns8390.h:163
#define D8390_P0_IMR
Definition ns8390.h:185
#define _3COM_PCFR_PIO
Definition ns8390.h:105
#define D8390_P0_TBCR1
Definition ns8390.h:175
#define _3COM_PCFR_C8000
Definition ns8390.h:106
#define _3COM_GACFR_TCM
Definition ns8390.h:126
#define D8390_COMMAND_PS1
Definition ns8390.h:197
#define WD_MSR
Definition ns8390.h:39
#define D8390_DCR_WTS
Definition ns8390.h:210
#define VENDOR_WD
Definition ns8390.h:12
#define WD_GP2
Definition ns8390.h:46
#define _3COM_CR_EALO
Definition ns8390.h:113
#define TYPE_WD8003S
Definition ns8390.h:62
#define _3COM_VPTR0
Definition ns8390.h:152
#define D8390_P0_RBCR1
Definition ns8390.h:180
#define _3COM_PSTR
Definition ns8390.h:92
#define D8390_P0_DCR
Definition ns8390.h:184
#define _3COM_GACFR
Definition ns8390.h:119
#define WD_LAAR_M16EN
Definition ns8390.h:55
#define D8390_P0_PSTART
Definition ns8390.h:169
#define TYPE_SMC8416C
Definition ns8390.h:74
#define D8390_P0_COMMAND
Definition ns8390.h:168
#define TYPE_WD8013EBT
Definition ns8390.h:64
#define _3COM_PCFR_DC000
Definition ns8390.h:109
#define D8390_P0_RSAR1
Definition ns8390.h:178
#define _3COM_PCFR_D8000
Definition ns8390.h:108
#define _3COM_PSPR
Definition ns8390.h:93
#define TYPE_WD8013EP
Definition ns8390.h:68
#define D8390_P0_TBCR0
Definition ns8390.h:174
#define D8390_P0_RSAR0
Definition ns8390.h:177
#define _3COM_CR_XSEL
Definition ns8390.h:112
#define TYPE_SMC8416T
Definition ns8390.h:73
#define D8390_COMMAND_PS0
Definition ns8390.h:196
#define MEM_8192
Definition ns8390.h:20
#define _3COM_CR
Definition ns8390.h:110
#define _3COM_STREG
Definition ns8390.h:128
#define NE_RESET
Definition ns8390.h:160
#define WD_LAAR_L16EN
Definition ns8390.h:54
#define D8390_COMMAND_RD0
Definition ns8390.h:201
#define D8390_COMMAND_RD1
Definition ns8390.h:200
#define D8390_P0_TPSR
Definition ns8390.h:173
#define D8390_DCR_LS
Definition ns8390.h:209
#define TYPE_WD8013EPC
Definition ns8390.h:70
#define D8390_ISR_OVW
Definition ns8390.h:216
#define WD_BID
Definition ns8390.h:48
#define _3COM_GACFR_MBS0
Definition ns8390.h:120
#define D8390_P0_ISR
Definition ns8390.h:176
#define WD_SOFTCONFIG
Definition ns8390.h:57
#define TYPE_SMC8216T
Definition ns8390.h:71
#define D8390_P0_RBCR0
Definition ns8390.h:179
#define TYPE_SMC8216C
Definition ns8390.h:72
#define MEM_16384
Definition ns8390.h:21
#define D8390_P1_PAR0
Definition ns8390.h:187
#define _3COM_GACFR_NIM
Definition ns8390.h:127
#define MEM_32768
Definition ns8390.h:22
#define _3COM_GACFR_RSEL
Definition ns8390.h:123
#define D8390_TXBUF_SIZE
Definition ns8390.h:226
#define ISA_MAX_ADDR
Definition ns8390.h:24
#define D8390_ISR_RDC
Definition ns8390.h:218
#define D8390_P0_RSR
Definition ns8390.h:181
#define _3COM_VPTR2
Definition ns8390.h:150
#define D8390_P0_RCR
Definition ns8390.h:182
#define WD_NIC_ADDR
Definition ns8390.h:34
#define _3COM_CR_DDIR
Definition ns8390.h:117
#define TYPE_WD8003E
Definition ns8390.h:63
#define _3COM_CR_START
Definition ns8390.h:118
#define _3COM_DAMSB
Definition ns8390.h:148
#define WD_MSR_MENB
Definition ns8390.h:52
#define FLAG_790
Definition ns8390.h:18
#define FLAG_PIO
Definition ns8390.h:16
#define D8390_COMMAND_TXP
Definition ns8390.h:202
#define VENDOR_3COM
Definition ns8390.h:14
#define _3COM_PCFR
Definition ns8390.h:104
#define _3COM_STREG_DPRDY
Definition ns8390.h:134
#define D8390_DCR_FT1
Definition ns8390.h:208
#define TYPE_SMC8013EBP
Definition ns8390.h:75
#define _3COM_PCFR_CC000
Definition ns8390.h:107
#define WD_LAR
Definition ns8390.h:47
#define WD_DEFAULT_MEM
Definition ns8390.h:32
#define D8390_P0_TCR
Definition ns8390.h:183
#define FLAG_16BIT
Definition ns8390.h:17
#define WD_LOW_BASE
Definition ns8390.h:29
#define _3COM_ASIC_OFFSET
Definition ns8390.h:89
#define _3COM_CR_RST
Definition ns8390.h:111
#define TYPE_WD8003W
Definition ns8390.h:65
#define D8390_COMMAND_RD2
Definition ns8390.h:199
#define _3COM_BCFR
Definition ns8390.h:95
#define _3COM_VPTR1
Definition ns8390.h:151
#define D8390_P1_MAR0
Definition ns8390.h:194
#define _3COM_DALSB
Definition ns8390.h:149
#define D8390_COMMAND_STP
Definition ns8390.h:204
#define TYPE_WD8003EB
Definition ns8390.h:66
#define D8390_P1_CURR
Definition ns8390.h:193
#define D8390_RCR_MON
Definition ns8390.h:206
PCI bus.
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition pci.h:308
static unsigned int x
Definition pixbuf.h:63
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ISA driver.
Definition isa.h:34
Definition nic.h:49
int flags
Definition nic.h:51
unsigned char * packet
Definition nic.h:53
unsigned char * node_addr
Definition nic.h:52
unsigned int packetlen
Definition nic.h:54
unsigned char irqno
Definition nic.h:56
unsigned int ioaddr
Definition nic.h:55
struct nic_operations * nic_op
Definition nic.h:50
A PCI device ID list entry.
Definition pci.h:175
A PCI device.
Definition pci.h:211
unsigned long ioaddr
I/O address.
Definition pci.h:226
A PCI driver.
Definition pci.h:252
unsigned char status
Definition ns8390.h:231
unsigned short len
Definition ns8390.h:233
unsigned char next
Definition ns8390.h:232
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:465