iPXE
ns8390.c
Go to the documentation of this file.
00001 /**************************************************************************
00002 ETHERBOOT -  BOOTP/TFTP Bootstrap Program
00003 
00004 Author: Martin Renters
00005   Date: May/94
00006 
00007  This code is based heavily on David Greenman's if_ed.c driver
00008 
00009  Copyright (C) 1993-1994, David Greenman, Martin Renters.
00010   This software may be used, modified, copied, distributed, and sold, in
00011   both source and binary form provided that the above copyright and these
00012   terms are retained. Under no circumstances are the authors responsible for
00013   the proper functioning of this software, nor do the authors assume any
00014   responsibility for damages incurred with its use.
00015 
00016 Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
00017 Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
00018 3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
00019 SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
00020 3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
00021 RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
00022   parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
00023 SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
00024   based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
00025 
00026 **************************************************************************/
00027 
00028 FILE_LICENCE ( BSD2 );
00029 
00030 /* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
00031 
00032 #if 1
00033 
00034 #if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
00035     !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
00036   /* The driver named ns8390 is the PCI driver, often called
00037      "PCI ne2000 clones". */
00038 # define INCLUDE_NS8390 1
00039 #endif
00040 
00041 #include "etherboot.h"
00042 #include "nic.h"
00043 #include "ns8390.h"
00044 #include <ipxe/ethernet.h>
00045 #ifdef  INCLUDE_NS8390
00046 #include <ipxe/pci.h>
00047 #else
00048 #include <ipxe/isa.h>
00049 #endif
00050 
00051 static unsigned char    eth_vendor, eth_flags;
00052 #ifdef  INCLUDE_WD
00053 static unsigned char    eth_laar;
00054 #endif
00055 static unsigned short   eth_nic_base, eth_asic_base;
00056 static unsigned char    eth_memsize, eth_rx_start, eth_tx_start;
00057 static Address          eth_bmem, eth_rmem;
00058 static unsigned char    eth_drain_receiver;
00059 
00060 #ifdef  INCLUDE_WD
00061 static struct wd_board {
00062         const char *name;
00063         char id;
00064         char flags;
00065         char memsize;
00066 } wd_boards[] = {
00067         {"WD8003S",     TYPE_WD8003S,   0,                      MEM_8192},
00068         {"WD8003E",     TYPE_WD8003E,   0,                      MEM_8192},
00069         {"WD8013EBT",   TYPE_WD8013EBT, FLAG_16BIT,             MEM_16384},
00070         {"WD8003W",     TYPE_WD8003W,   0,                      MEM_8192},
00071         {"WD8003EB",    TYPE_WD8003EB,  0,                      MEM_8192},
00072         {"WD8013W",     TYPE_WD8013W,   FLAG_16BIT,             MEM_16384},
00073         {"WD8003EP/WD8013EP",
00074                         TYPE_WD8013EP,  0,                      MEM_8192},
00075         {"WD8013WC",    TYPE_WD8013WC,  FLAG_16BIT,             MEM_16384},
00076         {"WD8013EPC",   TYPE_WD8013EPC, FLAG_16BIT,             MEM_16384},
00077         {"SMC8216T",    TYPE_SMC8216T,  FLAG_16BIT | FLAG_790,  MEM_16384},
00078         {"SMC8216C",    TYPE_SMC8216C,  FLAG_16BIT | FLAG_790,  MEM_16384},
00079         {"SMC8416T",    TYPE_SMC8416T,  FLAG_16BIT | FLAG_790,  MEM_8192},
00080         {"SMC8416C/BT", TYPE_SMC8416C,  FLAG_16BIT | FLAG_790,  MEM_8192},
00081         {"SMC8013EBP",  TYPE_SMC8013EBP,FLAG_16BIT,             MEM_16384},
00082         {NULL,          0,              0,                      0}
00083 };
00084 #endif
00085 
00086 #ifdef  INCLUDE_3C503
00087 static unsigned char    t503_output;    /* AUI or internal xcvr (Thinnet) */
00088 #endif
00089 
00090 #if     defined(INCLUDE_WD)
00091 #define ASIC_PIO        WD_IAR
00092 #define eth_probe       wd_probe
00093 #if     defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00094 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00095 #endif
00096 #endif
00097 
00098 #if     defined(INCLUDE_3C503)
00099 #define eth_probe       t503_probe
00100 #if     defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
00101 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00102 #endif
00103 #endif
00104 
00105 #if     defined(INCLUDE_NE)
00106 #define eth_probe       ne_probe
00107 #if     defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
00108 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00109 #endif
00110 #endif
00111 
00112 #if     defined(INCLUDE_NS8390)
00113 #define eth_probe       nepci_probe
00114 #if     defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
00115 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00116 #endif
00117 #endif
00118 
00119 #if     defined(INCLUDE_3C503)
00120 #define ASIC_PIO        _3COM_RFMSB
00121 #else
00122 #if     defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00123 #define ASIC_PIO        NE_DATA
00124 #endif
00125 #endif
00126 
00127 #if     defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
00128 /**************************************************************************
00129 ETH_PIO_READ - Read a frame via Programmed I/O
00130 **************************************************************************/
00131 static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
00132 {
00133 #ifdef  INCLUDE_WD
00134         outb(src & 0xff, eth_asic_base + WD_GP2);
00135         outb(src >> 8, eth_asic_base + WD_GP2);
00136 #else
00137         outb(D8390_COMMAND_RD2 |
00138                 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00139         outb(cnt, eth_nic_base + D8390_P0_RBCR0);
00140         outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
00141         outb(src, eth_nic_base + D8390_P0_RSAR0);
00142         outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
00143         outb(D8390_COMMAND_RD0 |
00144                 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00145 
00146 #ifdef  INCLUDE_3C503
00147         outb(src & 0xff, eth_asic_base + _3COM_DALSB);
00148         outb(src >> 8, eth_asic_base + _3COM_DAMSB);
00149         outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
00150 #endif
00151 #endif
00152 
00153         if (eth_flags & FLAG_16BIT)
00154                 cnt = (cnt + 1) >> 1;
00155 
00156         while(cnt--) {
00157 #ifdef  INCLUDE_3C503
00158                 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
00159                         ;
00160 #endif
00161 
00162                 if (eth_flags & FLAG_16BIT) {
00163                         *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
00164                         dst += 2;
00165                 }
00166                 else
00167                         *(dst++) = inb(eth_asic_base + ASIC_PIO);
00168         }
00169 
00170 #ifdef  INCLUDE_3C503
00171         outb(t503_output, eth_asic_base + _3COM_CR);
00172 #endif
00173 }
00174 
00175 /**************************************************************************
00176 ETH_PIO_WRITE - Write a frame via Programmed I/O
00177 **************************************************************************/
00178 static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
00179 {
00180 #ifdef  COMPEX_RL2000_FIX
00181         unsigned int x;
00182 #endif  /* COMPEX_RL2000_FIX */
00183 #ifdef  INCLUDE_WD
00184         outb(dst & 0xff, eth_asic_base + WD_GP2);
00185         outb(dst >> 8, eth_asic_base + WD_GP2);
00186 #else
00187         outb(D8390_COMMAND_RD2 |
00188                 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00189         outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
00190         outb(cnt, eth_nic_base + D8390_P0_RBCR0);
00191         outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
00192         outb(dst, eth_nic_base + D8390_P0_RSAR0);
00193         outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
00194         outb(D8390_COMMAND_RD1 |
00195                 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00196 
00197 #ifdef  INCLUDE_3C503
00198         outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
00199         outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
00200 
00201         outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
00202 #endif
00203 #endif
00204 
00205         if (eth_flags & FLAG_16BIT)
00206                 cnt = (cnt + 1) >> 1;
00207 
00208         while(cnt--)
00209         {
00210 #ifdef  INCLUDE_3C503
00211                 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
00212                         ;
00213 #endif
00214 
00215                 if (eth_flags & FLAG_16BIT) {
00216                         outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
00217                         src += 2;
00218                 }
00219                 else
00220                         outb(*(src++), eth_asic_base + ASIC_PIO);
00221         }
00222 
00223 #ifdef  INCLUDE_3C503
00224         outb(t503_output, eth_asic_base + _3COM_CR);
00225 #else
00226 #ifdef  COMPEX_RL2000_FIX
00227         for (x = 0;
00228                 x < COMPEX_RL2000_TRIES &&
00229                 (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
00230                 != D8390_ISR_RDC;
00231                 ++x);
00232         if (x >= COMPEX_RL2000_TRIES)
00233                 printf("Warning: Compex RL2000 aborted wait!\n");
00234 #endif  /* COMPEX_RL2000_FIX */
00235 #ifndef INCLUDE_WD
00236         while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
00237                 != D8390_ISR_RDC);
00238 #endif
00239 #endif
00240 }
00241 #else
00242 /**************************************************************************
00243 ETH_PIO_READ - Dummy routine when NE2000 not compiled in
00244 **************************************************************************/
00245 static void eth_pio_read(unsigned int src __unused, unsigned char *dst  __unused, unsigned int cnt __unused) {}
00246 #endif
00247 
00248 
00249 /**************************************************************************
00250 enable_multycast - Enable Multicast
00251 **************************************************************************/
00252 static void enable_multicast(unsigned short eth_nic_base) 
00253 {
00254         unsigned char mcfilter[8];
00255         int i;
00256         memset(mcfilter, 0xFF, 8);
00257         outb(4, eth_nic_base+D8390_P0_RCR);     
00258         outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
00259         for(i=0;i<8;i++)
00260         {
00261                 outb(mcfilter[i], eth_nic_base + 8 + i);
00262                 if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
00263                         printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
00264         }
00265         outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
00266         outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
00267 }
00268 
00269 /**************************************************************************
00270 NS8390_RESET - Reset adapter
00271 **************************************************************************/
00272 static void ns8390_reset(struct nic *nic)
00273 {
00274         int i;
00275 
00276         eth_drain_receiver = 0;
00277 #ifdef  INCLUDE_WD
00278         if (eth_flags & FLAG_790)
00279                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00280         else
00281 #endif
00282                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00283                         D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00284         if (eth_flags & FLAG_16BIT)
00285                 outb(0x49, eth_nic_base+D8390_P0_DCR);
00286         else
00287                 outb(0x48, eth_nic_base+D8390_P0_DCR);
00288         outb(0, eth_nic_base+D8390_P0_RBCR0);
00289         outb(0, eth_nic_base+D8390_P0_RBCR1);
00290         outb(0x20, eth_nic_base+D8390_P0_RCR);  /* monitor mode */
00291         outb(2, eth_nic_base+D8390_P0_TCR);
00292         outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
00293         outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
00294 #ifdef  INCLUDE_WD
00295         if (eth_flags & FLAG_790) {
00296 #ifdef  WD_790_PIO
00297                 outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
00298                 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
00299 #else
00300                 outb(0, eth_nic_base + 0x09);
00301 #endif
00302         }
00303 #endif
00304         outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
00305         outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
00306         outb(0xFF, eth_nic_base+D8390_P0_ISR);
00307         outb(0, eth_nic_base+D8390_P0_IMR);
00308 #ifdef  INCLUDE_WD
00309         if (eth_flags & FLAG_790)
00310                 outb(D8390_COMMAND_PS1 |
00311                         D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00312         else
00313 #endif
00314                 outb(D8390_COMMAND_PS1 |
00315                         D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00316         for (i=0; i<ETH_ALEN; i++)
00317                 outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
00318         for (i=0; i<ETH_ALEN; i++)
00319                 outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
00320         outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
00321 #ifdef  INCLUDE_WD
00322         if (eth_flags & FLAG_790)
00323                 outb(D8390_COMMAND_PS0 |
00324                         D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00325         else
00326 #endif
00327                 outb(D8390_COMMAND_PS0 |
00328                         D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00329         outb(0xFF, eth_nic_base+D8390_P0_ISR);
00330         outb(0, eth_nic_base+D8390_P0_TCR);     /* transmitter on */
00331         outb(4, eth_nic_base+D8390_P0_RCR);     /* allow rx broadcast frames */
00332 
00333         enable_multicast(eth_nic_base);
00334 
00335 #ifdef  INCLUDE_3C503
00336         /*
00337          * No way to tell whether or not we're supposed to use
00338          * the 3Com's transceiver unless the user tells us.
00339          * 'flags' should have some compile time default value
00340          * which can be changed from the command menu.
00341          */
00342         t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
00343         outb(t503_output, eth_asic_base + _3COM_CR);
00344 #endif
00345 }
00346 
00347 static int ns8390_poll(struct nic *nic, int retrieve);
00348 
00349 #ifndef INCLUDE_3C503
00350 /**************************************************************************
00351 ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
00352 **************************************************************************/
00353 static void eth_rx_overrun(struct nic *nic)
00354 {
00355         int start_time;
00356 
00357 #ifdef  INCLUDE_WD
00358         if (eth_flags & FLAG_790)
00359                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00360         else
00361 #endif
00362                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00363                         D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00364 
00365         /* wait for at least 1.6ms - we wait one timer tick */
00366         start_time = currticks();
00367         while (currticks() - start_time <= 1)
00368                 /* Nothing */;
00369 
00370         outb(0, eth_nic_base+D8390_P0_RBCR0);   /* reset byte counter */
00371         outb(0, eth_nic_base+D8390_P0_RBCR1);
00372 
00373         /*
00374          * Linux driver checks for interrupted TX here. This is not necessary,
00375          * because the transmit routine waits until the frame is sent.
00376          */
00377 
00378         /* enter loopback mode and restart NIC */
00379         outb(2, eth_nic_base+D8390_P0_TCR);
00380 #ifdef  INCLUDE_WD
00381         if (eth_flags & FLAG_790)
00382                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00383         else
00384 #endif
00385                 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00386                         D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00387 
00388         /* clear the RX ring, acknowledge overrun interrupt */
00389         eth_drain_receiver = 1;
00390         while (ns8390_poll(nic, 1))
00391                 /* Nothing */;
00392         eth_drain_receiver = 0;
00393         outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
00394 
00395         /* leave loopback mode - no packets to be resent (see Linux driver) */
00396         outb(0, eth_nic_base+D8390_P0_TCR);
00397 }
00398 #endif  /* INCLUDE_3C503 */
00399 
00400 /**************************************************************************
00401 NS8390_TRANSMIT - Transmit a frame
00402 **************************************************************************/
00403 static void ns8390_transmit(
00404         struct nic *nic,
00405         const char *d,                  /* Destination */
00406         unsigned int t,                 /* Type */
00407         unsigned int s,                 /* size */
00408         const char *p)                  /* Packet */
00409 {
00410 #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
00411         Address         eth_vmem = bus_to_virt(eth_bmem);
00412 #endif
00413 #ifdef  INCLUDE_3C503
00414         if (!(eth_flags & FLAG_PIO)) {
00415                 memcpy((char *)eth_vmem, d, ETH_ALEN);  /* dst */
00416                 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
00417                 *((char *)eth_vmem+12) = t>>8;          /* type */
00418                 *((char *)eth_vmem+13) = t;
00419                 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
00420                 s += ETH_HLEN;
00421                 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
00422         }
00423 #endif
00424 
00425 #ifdef  INCLUDE_WD
00426         if (eth_flags & FLAG_16BIT) {
00427                 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00428                 inb(0x84);
00429         }
00430 #ifndef WD_790_PIO
00431         /* Memory interface */
00432         if (eth_flags & FLAG_790) {
00433                 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
00434                 inb(0x84);
00435         }
00436         inb(0x84);
00437         memcpy((char *)eth_vmem, d, ETH_ALEN);  /* dst */
00438         memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
00439         *((char *)eth_vmem+12) = t>>8;          /* type */
00440         *((char *)eth_vmem+13) = t;
00441         memcpy((char *)eth_vmem+ETH_HLEN, p, s);
00442         s += ETH_HLEN;
00443         while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
00444         if (eth_flags & FLAG_790) {
00445                 outb(0, eth_asic_base + WD_MSR);
00446                 inb(0x84);
00447         }
00448 #else
00449         inb(0x84);
00450 #endif
00451 #endif
00452 
00453 #if     defined(INCLUDE_3C503)
00454         if (eth_flags & FLAG_PIO)
00455 #endif
00456 #if     defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
00457         {
00458                 /* Programmed I/O */
00459                 unsigned short type;
00460                 type = (t >> 8) | (t << 8);
00461                 eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
00462                 eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
00463                 /* bcc generates worse code without (const+const) below */
00464                 eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
00465                 eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
00466                 s += ETH_HLEN;
00467                 if (s < ETH_ZLEN) s = ETH_ZLEN;
00468         }
00469 #endif
00470 #if     defined(INCLUDE_3C503)
00471 #endif
00472 
00473 #ifdef  INCLUDE_WD
00474         if (eth_flags & FLAG_16BIT) {
00475                 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00476                 inb(0x84);
00477         }
00478         if (eth_flags & FLAG_790)
00479                 outb(D8390_COMMAND_PS0 |
00480                         D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00481         else
00482 #endif
00483                 outb(D8390_COMMAND_PS0 |
00484                         D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00485         outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
00486         outb(s, eth_nic_base+D8390_P0_TBCR0);
00487         outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
00488 #ifdef  INCLUDE_WD
00489         if (eth_flags & FLAG_790)
00490                 outb(D8390_COMMAND_PS0 |
00491                         D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00492         else
00493 #endif
00494                 outb(D8390_COMMAND_PS0 |
00495                         D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
00496                         D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00497 }
00498 
00499 /**************************************************************************
00500 NS8390_POLL - Wait for a frame
00501 **************************************************************************/
00502 static int ns8390_poll(struct nic *nic, int retrieve)
00503 {
00504         int ret = 0;
00505         unsigned char rstat, curr, next;
00506         unsigned short len, frag;
00507         unsigned short pktoff;
00508         unsigned char *p;
00509         struct ringbuffer pkthdr;
00510 
00511 #ifndef INCLUDE_3C503
00512         /* avoid infinite recursion: see eth_rx_overrun() */
00513         if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
00514                 eth_rx_overrun(nic);
00515                 return(0);
00516         }
00517 #endif  /* INCLUDE_3C503 */
00518         rstat = inb(eth_nic_base+D8390_P0_RSR);
00519         if (!(rstat & D8390_RSTAT_PRX)) return(0);
00520         next = inb(eth_nic_base+D8390_P0_BOUND)+1;
00521         if (next >= eth_memsize) next = eth_rx_start;
00522         outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
00523         curr = inb(eth_nic_base+D8390_P1_CURR);
00524         outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
00525         if (curr >= eth_memsize) curr=eth_rx_start;
00526         if (curr == next) return(0);
00527 
00528         if ( ! retrieve ) return 1;
00529 
00530 #ifdef  INCLUDE_WD
00531         if (eth_flags & FLAG_16BIT) {
00532                 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00533                 inb(0x84);
00534         }
00535 #ifndef WD_790_PIO
00536         if (eth_flags & FLAG_790) {
00537                 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
00538                 inb(0x84);
00539         }
00540 #endif
00541         inb(0x84);
00542 #endif
00543         pktoff = next << 8;
00544         if (eth_flags & FLAG_PIO)
00545                 eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
00546         else
00547                 memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
00548         pktoff += sizeof(pkthdr);
00549         /* incoming length includes FCS so must sub 4 */
00550         len = pkthdr.len - 4;
00551         if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
00552                 || len > ETH_FRAME_LEN) {
00553                 printf("Bogus packet, ignoring\n");
00554                 return (0);
00555         }
00556         else {
00557                 p = nic->packet;
00558                 nic->packetlen = len;           /* available to caller */
00559                 frag = (eth_memsize << 8) - pktoff;
00560                 if (len > frag) {               /* We have a wrap-around */
00561                         /* read first part */
00562                         if (eth_flags & FLAG_PIO)
00563                                 eth_pio_read(pktoff, p, frag);
00564                         else
00565                                 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
00566                         pktoff = eth_rx_start << 8;
00567                         p += frag;
00568                         len -= frag;
00569                 }
00570                 /* read second part */
00571                 if (eth_flags & FLAG_PIO)
00572                         eth_pio_read(pktoff, p, len);
00573                 else
00574                         memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
00575                 ret = 1;
00576         }
00577 #ifdef  INCLUDE_WD
00578 #ifndef WD_790_PIO
00579         if (eth_flags & FLAG_790) {
00580                 outb(0, eth_asic_base + WD_MSR);
00581                 inb(0x84);
00582         }
00583 #endif
00584         if (eth_flags & FLAG_16BIT) {
00585                 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00586                 inb(0x84);
00587         }
00588         inb(0x84);
00589 #endif
00590         next = pkthdr.next;             /* frame number of next packet */
00591         if (next == eth_rx_start)
00592                 next = eth_memsize;
00593         outb(next-1, eth_nic_base+D8390_P0_BOUND);
00594         return(ret);
00595 }
00596 
00597 /**************************************************************************
00598 NS8390_DISABLE - Turn off adapter
00599 **************************************************************************/
00600 static void ns8390_disable ( struct nic *nic ) {
00601         ns8390_reset(nic);
00602 }
00603 
00604 /**************************************************************************
00605 NS8390_IRQ - Enable, Disable, or Force interrupts
00606 **************************************************************************/
00607 static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
00608 {
00609   switch ( action ) {
00610   case DISABLE :
00611     break;
00612   case ENABLE :
00613     break;
00614   case FORCE :
00615     break;
00616   }
00617 }
00618 
00619 static struct nic_operations ns8390_operations;
00620 static struct nic_operations ns8390_operations = {
00621         .connect        = dummy_connect,
00622         .poll           = ns8390_poll,
00623         .transmit       = ns8390_transmit,
00624         .irq            = ns8390_irq,
00625 };
00626 
00627 /**************************************************************************
00628 ETH_PROBE - Look for an adapter
00629 **************************************************************************/
00630 #ifdef  INCLUDE_NS8390
00631 static int eth_probe (struct nic *nic, struct pci_device *pci)
00632 #else
00633 static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
00634 #endif
00635 {
00636         int i;
00637 #ifdef INCLUDE_NS8390
00638         unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
00639         unsigned short *probe_addrs = pci_probe_addrs;
00640 #endif
00641         eth_vendor = VENDOR_NONE;
00642         eth_drain_receiver = 0;
00643 
00644         nic->irqno  = 0;
00645 
00646 #ifdef  INCLUDE_WD
00647 {
00648         /******************************************************************
00649         Search for WD/SMC cards
00650         ******************************************************************/
00651         struct wd_board *brd;
00652         unsigned short chksum;
00653         unsigned char c;
00654         for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
00655                 eth_asic_base += 0x20) {
00656                 chksum = 0;
00657                 for (i=8; i<16; i++)
00658                         chksum += inb(eth_asic_base+i);
00659                 /* Extra checks to avoid soundcard */
00660                 if ((chksum & 0xFF) == 0xFF &&
00661                         inb(eth_asic_base+8) != 0xFF &&
00662                         inb(eth_asic_base+9) != 0xFF)
00663                         break;
00664         }
00665         if (eth_asic_base > WD_HIGH_BASE)
00666                 return (0);
00667         /* We've found a board */
00668         eth_vendor = VENDOR_WD;
00669         eth_nic_base = eth_asic_base + WD_NIC_ADDR;
00670 
00671         nic->ioaddr = eth_nic_base;
00672 
00673         c = inb(eth_asic_base+WD_BID);  /* Get board id */
00674         for (brd = wd_boards; brd->name; brd++)
00675                 if (brd->id == c) break;
00676         if (!brd->name) {
00677                 printf("Unknown WD/SMC NIC type %hhX\n", c);
00678                 return (0);     /* Unknown type */
00679         }
00680         eth_flags = brd->flags;
00681         eth_memsize = brd->memsize;
00682         eth_tx_start = 0;
00683         eth_rx_start = D8390_TXBUF_SIZE;
00684         if ((c == TYPE_WD8013EP) &&
00685                 (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
00686                         eth_flags = FLAG_16BIT;
00687                         eth_memsize = MEM_16384;
00688         }
00689         if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
00690                 eth_bmem = (0x80000 |
00691                  ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
00692         } else
00693                 eth_bmem = WD_DEFAULT_MEM;
00694         if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
00695                 /* from Linux driver, 8416BT detects as 8216 sometimes */
00696                 unsigned int addr = inb(eth_asic_base + 0xb);
00697                 if (((addr >> 4) & 3) == 0) {
00698                         brd += 2;
00699                         eth_memsize = brd->memsize;
00700                 }
00701         }
00702         outb(0x80, eth_asic_base + WD_MSR);     /* Reset */
00703         for (i=0; i<ETH_ALEN; i++) {
00704                 nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
00705         }
00706         DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
00707         if (eth_flags & FLAG_790) {
00708 #ifdef  WD_790_PIO
00709                 DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
00710                 eth_bmem = 0;
00711                 eth_flags |= FLAG_PIO;          /* force PIO mode */
00712                 outb(0, eth_asic_base+WD_MSR);
00713 #else
00714                 DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
00715 
00716                 outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
00717                 outb((inb(eth_asic_base+0x04) |
00718                         0x80), eth_asic_base+0x04);
00719                 outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
00720                         ((unsigned)(eth_bmem >> 11) & 0x40) |
00721                         (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
00722                 outb((inb(eth_asic_base+0x04) &
00723                         ~0x80), eth_asic_base+0x04);
00724 #endif
00725         } else {
00726 
00727                 DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
00728 
00729                 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
00730         }
00731         if (eth_flags & FLAG_16BIT) {
00732                 if (eth_flags & FLAG_790) {
00733                         eth_laar = inb(eth_asic_base + WD_LAAR);
00734                         outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00735                 } else {
00736                         outb((eth_laar =
00737                                 WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
00738 /*
00739         The previous line used to be
00740                                 WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
00741         jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
00742         it work for WD8013s.  This seems to work for my 8013 boards. I
00743         don't know what is really happening.  I wish I had data sheets
00744         or more time to decode the Linux driver. - Ken
00745 */
00746                 }
00747                 inb(0x84);
00748         }
00749 }
00750 #endif
00751 #ifdef  INCLUDE_3C503
00752 #ifdef  T503_AUI
00753         nic->flags = 1;         /* aui */
00754 #else
00755         nic->flags = 0;         /* no aui */
00756 #endif
00757         /******************************************************************
00758         Search for 3Com 3c503 if no WD/SMC cards
00759         ******************************************************************/
00760         if (eth_vendor == VENDOR_NONE) {
00761                 int     idx;
00762                 int     iobase_reg, membase_reg;
00763                 static unsigned short   base[] = {
00764                         0x300, 0x310, 0x330, 0x350,
00765                         0x250, 0x280, 0x2A0, 0x2E0, 0 };
00766 
00767                 /* Loop through possible addresses checking each one */
00768 
00769                 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
00770 
00771                         eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
00772 /*
00773  * Note that we use the same settings for both 8 and 16 bit cards:
00774  * both have an 8K bank of memory at page 1 while only the 16 bit
00775  * cards have a bank at page 0.
00776  */
00777                         eth_memsize = MEM_16384;
00778                         eth_tx_start = 32;
00779                         eth_rx_start = 32 + D8390_TXBUF_SIZE;
00780 
00781                 /* Check our base address. iobase and membase should */
00782                 /* both have a maximum of 1 bit set or be 0. */
00783 
00784                         iobase_reg = inb(eth_asic_base + _3COM_BCFR);
00785                         membase_reg = inb(eth_asic_base + _3COM_PCFR);
00786 
00787                         if ((iobase_reg & (iobase_reg - 1)) ||
00788                                 (membase_reg & (membase_reg - 1)))
00789                                 continue;               /* nope */
00790 
00791                 /* Now get the shared memory address */
00792 
00793                         eth_flags = 0;
00794 
00795                         switch (membase_reg) {
00796                                 case _3COM_PCFR_DC000:
00797                                         eth_bmem = 0xdc000;
00798                                         break;
00799                                 case _3COM_PCFR_D8000:
00800                                         eth_bmem = 0xd8000;
00801                                         break;
00802                                 case _3COM_PCFR_CC000:
00803                                         eth_bmem = 0xcc000;
00804                                         break;
00805                                 case _3COM_PCFR_C8000:
00806                                         eth_bmem = 0xc8000;
00807                                         break;
00808                                 case _3COM_PCFR_PIO:
00809                                         eth_flags |= FLAG_PIO;
00810                                         eth_bmem = 0;
00811                                         break;
00812                                 default:
00813                                         continue;       /* nope */
00814                                 }
00815                         break;
00816                 }
00817 
00818                 if (base[idx] == 0)             /* not found */
00819                         return (0);
00820 #ifndef T503_SHMEM
00821                 eth_flags |= FLAG_PIO;          /* force PIO mode */
00822                 eth_bmem = 0;
00823 #endif
00824                 eth_vendor = VENDOR_3COM;
00825 
00826 
00827         /* Need this to make ns8390_poll() happy. */
00828 
00829                 eth_rmem = eth_bmem - 0x2000;
00830 
00831         /* Reset NIC and ASIC */
00832 
00833                 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
00834                 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
00835 
00836         /* Get our ethernet address */
00837 
00838                 outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
00839                 nic->ioaddr = eth_nic_base;
00840                 DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
00841                 if (eth_flags & FLAG_PIO)
00842                         DBG ( "PIO mode" );
00843                 else
00844                         DBG ( "memory %4.4x", eth_bmem );
00845                 for (i=0; i<ETH_ALEN; i++) {
00846                         nic->node_addr[i] = inb(eth_nic_base+i);
00847                 }
00848                 DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
00849                       eth_ntoa ( nic->node_addr ) );
00850 
00851                 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
00852         /*
00853          * Initialize GA configuration register. Set bank and enable shared
00854          * mem. We always use bank 1. Disable interrupts.
00855          */
00856                 outb(_3COM_GACFR_RSEL |
00857                         _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
00858 
00859                 outb(0xff, eth_asic_base + _3COM_VPTR2);
00860                 outb(0xff, eth_asic_base + _3COM_VPTR1);
00861                 outb(0x00, eth_asic_base + _3COM_VPTR0);
00862         /*
00863          * Clear memory and verify that it worked (we use only 8K)
00864          */
00865 
00866                 if (!(eth_flags & FLAG_PIO)) {
00867                         memset(bus_to_virt(eth_bmem), 0, 0x2000);
00868                         for(i = 0; i < 0x2000; ++i)
00869                                 if (*((char *)(bus_to_virt(eth_bmem+i)))) {
00870                                         printf ("Failed to clear 3c503 shared mem.\n");
00871                                         return (0);
00872                                 }
00873                 }
00874         /*
00875          * Initialize GA page/start/stop registers.
00876          */
00877                 outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
00878                 outb(eth_memsize, eth_asic_base + _3COM_PSPR);
00879         }
00880 #endif
00881 #if     defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00882 {
00883         /******************************************************************
00884         Search for NE1000/2000 if no WD/SMC or 3com cards
00885         ******************************************************************/
00886         unsigned char c;
00887         if (eth_vendor == VENDOR_NONE) {
00888                 unsigned char romdata[16];
00889                 unsigned char testbuf[32];
00890                 int idx;
00891                 static unsigned char test[] = "NE*000 memory";
00892                 static unsigned short base[] = {
00893 #ifdef  NE_SCAN
00894                         NE_SCAN,
00895 #endif
00896                         0 };
00897                 /* if no addresses supplied, fall back on defaults */
00898                 if (probe_addrs == NULL || probe_addrs[0] == 0)
00899                         probe_addrs = base;
00900                 eth_bmem = 0;           /* No shared memory */
00901                 for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
00902                         eth_flags = FLAG_PIO;
00903                         eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
00904                         eth_memsize = MEM_16384;
00905                         eth_tx_start = 32;
00906                         eth_rx_start = 32 + D8390_TXBUF_SIZE;
00907                         c = inb(eth_asic_base + NE_RESET);
00908                         outb(c, eth_asic_base + NE_RESET);
00909                         (void) inb(0x84);
00910                         outb(D8390_COMMAND_STP |
00911                                 D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
00912                         outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
00913                         outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
00914                         outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
00915                         outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
00916 #ifdef  NS8390_FORCE_16BIT
00917                         eth_flags |= FLAG_16BIT;        /* force 16-bit mode */
00918 #endif
00919 
00920                         eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
00921                         eth_pio_read(8192, testbuf, sizeof(test));
00922                         if (!memcmp(test, testbuf, sizeof(test)))
00923                                 break;
00924                         eth_flags |= FLAG_16BIT;
00925                         eth_memsize = MEM_32768;
00926                         eth_tx_start = 64;
00927                         eth_rx_start = 64 + D8390_TXBUF_SIZE;
00928                         outb(D8390_DCR_WTS |
00929                                 D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
00930                         outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
00931                         outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
00932                         eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
00933                         eth_pio_read(16384, testbuf, sizeof(test));
00934                         if (!memcmp(testbuf, test, sizeof(test)))
00935                                 break;
00936                 }
00937                 if (eth_nic_base == 0)
00938                         return (0);
00939                 if (eth_nic_base > ISA_MAX_ADDR)        /* PCI probably */
00940                         eth_flags |= FLAG_16BIT;
00941                 eth_vendor = VENDOR_NOVELL;
00942                 eth_pio_read(0, romdata, sizeof(romdata));
00943                 for (i=0; i<ETH_ALEN; i++) {
00944                         nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
00945                 }
00946                 nic->ioaddr = eth_nic_base;
00947                 DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
00948                       (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
00949                       eth_ntoa ( nic->node_addr ) );
00950         }
00951 }
00952 #endif
00953         if (eth_vendor == VENDOR_NONE)
00954                 return(0);
00955         if (eth_vendor != VENDOR_3COM)
00956                 eth_rmem = eth_bmem;
00957         ns8390_reset(nic);
00958         nic->nic_op     = &ns8390_operations;
00959 
00960         /* Based on PnP ISA map */
00961 #ifdef  INCLUDE_WD
00962         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00963         dev->devid.device_id = htons(0x812a);
00964 #endif
00965 #ifdef  INCLUDE_3C503
00966         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00967         dev->devid.device_id = htons(0x80f3);
00968 #endif
00969 #ifdef  INCLUDE_NE
00970         dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00971         dev->devid.device_id = htons(0x80d6);
00972 #endif
00973         return 1;
00974 }
00975 
00976 #ifdef  INCLUDE_WD
00977 struct isa_driver wd_driver __isa_driver = {
00978         .type    = NIC_DRIVER,
00979         .name    = "WD",
00980         .probe   = wd_probe,
00981         .ioaddrs = 0, 
00982 };
00983 ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
00984 #endif
00985 
00986 #ifdef  INCLUDE_3C503
00987 struct isa_driver t503_driver __isa_driver = {
00988         .type    = NIC_DRIVER,
00989         .name    = "3C503",
00990         .probe   = t503_probe,
00991         .ioaddrs = 0, 
00992 };
00993 ISA_ROM("3c503","3Com503, Etherlink II[/16]");
00994 #endif
00995 
00996 #ifdef  INCLUDE_NE
00997 struct isa_driver ne_driver __isa_driver = {
00998         .type    = NIC_DRIVER,
00999         .name    = "NE*000",
01000         .probe   = ne_probe,
01001         .ioaddrs = 0, 
01002 };
01003 ISA_ROM("ne","NE1000/2000 and clones");
01004 #endif
01005 
01006 #ifdef  INCLUDE_NS8390
01007 static struct pci_device_id nepci_nics[] = {
01008 /* A few NE2000 PCI clones, list not exhaustive */
01009 PCI_ROM(0x10ec, 0x8029, "rtl8029",      "Realtek 8029", 0),
01010 PCI_ROM(0x1186, 0x0300, "dlink-528",    "D-Link DE-528", 0),
01011 PCI_ROM(0x1050, 0x0940, "winbond940",   "Winbond NE2000-PCI", 0),               /* Winbond 86C940 / 89C940 */
01012 PCI_ROM(0x1050, 0x5a5a, "winbond940f",  "Winbond W89c940F", 0),         /* Winbond 89C940F */
01013 PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
01014 PCI_ROM(0x8e2e, 0x3000, "ktiet32p2",    "KTI ET32P2", 0),
01015 PCI_ROM(0x4a14, 0x5000, "nv5000sc",     "NetVin NV5000SC", 0),
01016 PCI_ROM(0x12c3, 0x0058, "holtek80232",  "Holtek HT80232", 0),
01017 PCI_ROM(0x12c3, 0x5598, "holtek80229",  "Holtek HT80229", 0),
01018 PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
01019 PCI_ROM(0x1106, 0x0926, "via86c926",    "Via 86c926", 0),
01020 };
01021 
01022 PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
01023 
01024 DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
01025          nepci_probe, ns8390_disable );
01026 
01027 #endif /* INCLUDE_NS8390 */
01028 
01029 #endif
01030 
01031 /*
01032  * Local variables:
01033  *  c-basic-offset: 8
01034  *  c-indent-level: 8
01035  *  tab-width: 8
01036  * End:
01037  */