rtl8139.c

Go to the documentation of this file.
00001 /* rtl8139.c - etherboot driver for the Realtek 8139 chipset
00002 
00003   ported from the linux driver written by Donald Becker
00004   by Rainer Bawidamann (Rainer.Bawidamann@informatik.uni-ulm.de) 1999
00005 
00006   This software may be used and distributed according to the terms
00007   of the GNU Public License, incorporated herein by reference.
00008 
00009   changes to the original driver:
00010   - removed support for interrupts, switching to polling mode (yuck!)
00011   - removed support for the 8129 chip (external MII)
00012 
00013 */
00014 
00015 FILE_LICENCE ( GPL_ANY );
00016 
00017 /*********************************************************************/
00018 /* Revision History                                                  */
00019 /*********************************************************************/
00020 
00021 /*
00022   27 May 2006   mcb30@users.sourceforge.net (Michael Brown)
00023      Rewrote to use the new net driver API, the updated PCI API, and
00024      the generic three-wire serial device support for EEPROM access.
00025 
00026   28 Dec 2002   ken_yap@users.sourceforge.net (Ken Yap)
00027      Put in virt_to_bus calls to allow Etherboot relocation.
00028 
00029   06 Apr 2001   ken_yap@users.sourceforge.net (Ken Yap)
00030      Following email from Hyun-Joon Cha, added a disable routine, otherwise
00031      NIC remains live and can crash the kernel later.
00032 
00033   4 Feb 2000    espenlaub@informatik.uni-ulm.de (Klaus Espenlaub)
00034      Shuffled things around, removed the leftovers from the 8129 support
00035      that was in the Linux driver and added a bit more 8139 definitions.
00036      Moved the 8K receive buffer to a fixed, available address outside the
00037      0x98000-0x9ffff range.  This is a bit of a hack, but currently the only
00038      way to make room for the Etherboot features that need substantial amounts
00039      of code like the ANSI console support.  Currently the buffer is just below
00040      0x10000, so this even conforms to the tagged boot image specification,
00041      which reserves the ranges 0x00000-0x10000 and 0x98000-0xA0000.  My
00042      interpretation of this "reserved" is that Etherboot may do whatever it
00043      likes, as long as its environment is kept intact (like the BIOS
00044      variables).  Hopefully fixed rtl_poll() once and for all.  The symptoms
00045      were that if Etherboot was left at the boot menu for several minutes, the
00046      first eth_poll failed.  Seems like I am the only person who does this.
00047      First of all I fixed the debugging code and then set out for a long bug
00048      hunting session.  It took me about a week full time work - poking around
00049      various places in the driver, reading Don Becker's and Jeff Garzik's Linux
00050      driver and even the FreeBSD driver (what a piece of crap!) - and
00051      eventually spotted the nasty thing: the transmit routine was acknowledging
00052      each and every interrupt pending, including the RxOverrun and RxFIFIOver
00053      interrupts.  This confused the RTL8139 thoroughly.  It destroyed the
00054      Rx ring contents by dumping the 2K FIFO contents right where we wanted to
00055      get the next packet.  Oh well, what fun.
00056 
00057   18 Jan 2000   mdc@etherboot.org (Marty Connor)
00058      Drastically simplified error handling.  Basically, if any error
00059      in transmission or reception occurs, the card is reset.
00060      Also, pointed all transmit descriptors to the same buffer to
00061      save buffer space.  This should decrease driver size and avoid
00062      corruption because of exceeding 32K during runtime.
00063 
00064   28 Jul 1999   (Matthias Meixner - meixner@rbg.informatik.tu-darmstadt.de)
00065      rtl_poll was quite broken: it used the RxOK interrupt flag instead
00066      of the RxBufferEmpty flag which often resulted in very bad
00067      transmission performace - below 1kBytes/s.
00068 
00069 */
00070 
00071 #include <stdint.h>
00072 #include <stdlib.h>
00073 #include <stdio.h>
00074 #include <string.h>
00075 #include <gpxe/io.h>
00076 #include <errno.h>
00077 #include <unistd.h>
00078 #include <byteswap.h>
00079 #include <gpxe/pci.h>
00080 #include <gpxe/if_ether.h>
00081 #include <gpxe/ethernet.h>
00082 #include <gpxe/iobuf.h>
00083 #include <gpxe/netdevice.h>
00084 #include <gpxe/spi_bit.h>
00085 #include <gpxe/threewire.h>
00086 #include <gpxe/nvo.h>
00087 
00088 #define TX_RING_SIZE 4
00089 
00090 struct rtl8139_tx {
00091         unsigned int next;
00092         struct io_buffer *iobuf[TX_RING_SIZE];
00093 };
00094 
00095 struct rtl8139_rx {
00096         void *ring;
00097         unsigned int offset;
00098 };
00099 
00100 struct rtl8139_nic {
00101         unsigned short ioaddr;
00102         struct rtl8139_tx tx;
00103         struct rtl8139_rx rx;
00104         struct spi_bit_basher spibit;
00105         struct spi_device eeprom;
00106         struct nvo_block nvo;
00107 };
00108 
00109 /* Tuning Parameters */
00110 #define TX_FIFO_THRESH  256     /* In bytes, rounded down to 32 byte units. */
00111 #define RX_FIFO_THRESH  4       /* Rx buffer level before first PCI xfer.  */
00112 #define RX_DMA_BURST    4       /* Maximum PCI burst, '4' is 256 bytes */
00113 #define TX_DMA_BURST    4       /* Calculate as 16<<val. */
00114 #define TX_IPG          3       /* This is the only valid value */
00115 #define RX_BUF_LEN_IDX  0       /* 0, 1, 2 is allowed - 8,16,32K rx buffer */
00116 #define RX_BUF_LEN ( (8192 << RX_BUF_LEN_IDX) )
00117 #define RX_BUF_PAD 4
00118 
00119 /* Symbolic offsets to registers. */
00120 enum RTL8139_registers {
00121         MAC0=0,                 /* Ethernet hardware address. */
00122         MAR0=8,                 /* Multicast filter. */
00123         TxStatus0=0x10,         /* Transmit status (four 32bit registers). */
00124         TxAddr0=0x20,           /* Tx descriptors (also four 32bit). */
00125         RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
00126         ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
00127         IntrMask=0x3C, IntrStatus=0x3E,
00128         TxConfig=0x40, RxConfig=0x44,
00129         Timer=0x48,             /* general-purpose counter. */
00130         RxMissed=0x4C,          /* 24 bits valid, write clears. */
00131         Cfg9346=0x50, Config0=0x51, Config1=0x52,
00132         TimerIntrReg=0x54,      /* intr if gp counter reaches this value */
00133         MediaStatus=0x58,
00134         Config3=0x59,
00135         MultiIntr=0x5C,
00136         RevisionID=0x5E,        /* revision of the RTL8139 chip */
00137         TxSummary=0x60,
00138         MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
00139         NWayExpansion=0x6A,
00140         DisconnectCnt=0x6C, FalseCarrierCnt=0x6E,
00141         NWayTestReg=0x70,
00142         RxCnt=0x72,             /* packet received counter */
00143         CSCR=0x74,              /* chip status and configuration register */
00144         PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80,   /* undocumented */
00145         /* from 0x84 onwards are a number of power management/wakeup frame
00146          * definitions we will probably never need to know about.  */
00147 };
00148 
00149 enum RxEarlyStatusBits {
00150         ERGood=0x08, ERBad=0x04, EROVW=0x02, EROK=0x01
00151 };
00152 
00153 enum ChipCmdBits {
00154         CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };
00155 
00156 enum IntrMaskBits {
00157         SERR=0x8000, TimeOut=0x4000, LenChg=0x2000,
00158         FOVW=0x40, PUN_LinkChg=0x20, RXOVW=0x10,
00159         TER=0x08, TOK=0x04, RER=0x02, ROK=0x01
00160 };
00161 
00162 /* Interrupt register bits, using my own meaningful names. */
00163 enum IntrStatusBits {
00164         PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000,
00165         RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
00166         TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,
00167 };
00168 enum TxStatusBits {
00169         TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
00170         TxOutOfWindow=0x20000000, TxAborted=0x40000000,
00171         TxCarrierLost=0x80000000,
00172 };
00173 enum RxStatusBits {
00174         RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
00175         RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
00176         RxBadAlign=0x0002, RxStatusOK=0x0001,
00177 };
00178 
00179 enum MediaStatusBits {
00180         MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08,
00181         MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01,
00182 };
00183 
00184 enum MIIBMCRBits {
00185         BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000,
00186         BMCRRestartNWay=0x0200, BMCRDuplex=0x0100,
00187 };
00188 
00189 enum CSCRBits {
00190         CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
00191         CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
00192         CSCR_LinkDownCmd=0x0f3c0,
00193 };
00194 
00195 enum RxConfigBits {
00196         RxCfgWrap=0x80,
00197         Eeprom9356=0x40,
00198         AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
00199         AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
00200 };
00201 
00202 enum Config1Bits {
00203         VPDEnable=0x02,
00204 };
00205 
00206 /*  EEPROM access */
00207 #define EE_M1           0x80    /* Mode select bit 1 */
00208 #define EE_M0           0x40    /* Mode select bit 0 */
00209 #define EE_CS           0x08    /* EEPROM chip select */
00210 #define EE_SK           0x04    /* EEPROM shift clock */
00211 #define EE_DI           0x02    /* Data in */
00212 #define EE_DO           0x01    /* Data out */
00213 
00214 /* Offsets within EEPROM (these are word offsets) */
00215 #define EE_MAC 7
00216 
00217 static const uint8_t rtl_ee_bits[] = {
00218         [SPI_BIT_SCLK]  = EE_SK,
00219         [SPI_BIT_MOSI]  = EE_DI,
00220         [SPI_BIT_MISO]  = EE_DO,
00221         [SPI_BIT_SS(0)] = ( EE_CS | EE_M1 ),
00222 };
00223 
00224 static int rtl_spi_read_bit ( struct bit_basher *basher,
00225                               unsigned int bit_id ) {
00226         struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic,
00227                                                  spibit.basher );
00228         uint8_t mask = rtl_ee_bits[bit_id];
00229         uint8_t eereg;
00230 
00231         eereg = inb ( rtl->ioaddr + Cfg9346 );
00232         return ( eereg & mask );
00233 }
00234 
00235 static void rtl_spi_write_bit ( struct bit_basher *basher,
00236                                 unsigned int bit_id, unsigned long data ) {
00237         struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic,
00238                                                  spibit.basher );
00239         uint8_t mask = rtl_ee_bits[bit_id];
00240         uint8_t eereg;
00241 
00242         eereg = inb ( rtl->ioaddr + Cfg9346 );
00243         eereg &= ~mask;
00244         eereg |= ( data & mask );
00245         outb ( eereg, rtl->ioaddr + Cfg9346 );
00246 }
00247 
00248 static struct bit_basher_operations rtl_basher_ops = {
00249         .read = rtl_spi_read_bit,
00250         .write = rtl_spi_write_bit,
00251 };
00252 
00253 /** Portion of EEPROM available for non-volatile stored options
00254  *
00255  * We use offset 0x40 (i.e. address 0x20), length 0x40.  This block is
00256  * marked as VPD in the rtl8139 datasheets, so we use it only if we
00257  * detect that the card is not supporting VPD.
00258  */
00259 static struct nvo_fragment rtl_nvo_fragments[] = {
00260         { 0x20, 0x40 },
00261         { 0, 0 }
00262 };
00263 
00264 /**
00265  * Set up for EEPROM access
00266  *
00267  * @v netdev            Net device
00268  */
00269 static void rtl_init_eeprom ( struct net_device *netdev ) {
00270         struct rtl8139_nic *rtl = netdev->priv;
00271         int ee9356;
00272         int vpd;
00273 
00274         /* Initialise three-wire bus */
00275         rtl->spibit.basher.op = &rtl_basher_ops;
00276         rtl->spibit.bus.mode = SPI_MODE_THREEWIRE;
00277         init_spi_bit_basher ( &rtl->spibit );
00278 
00279         /* Detect EEPROM type and initialise three-wire device */
00280         ee9356 = ( inw ( rtl->ioaddr + RxConfig ) & Eeprom9356 );
00281         if ( ee9356 ) {
00282                 DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C56\n", rtl );
00283                 init_at93c56 ( &rtl->eeprom, 16 );
00284         } else {
00285                 DBGC ( rtl, "rtl8139 %p EEPROM is an AT93C46\n", rtl );
00286                 init_at93c46 ( &rtl->eeprom, 16 );
00287         }
00288         rtl->eeprom.bus = &rtl->spibit.bus;
00289 
00290         /* Initialise space for non-volatile options, if available */
00291         vpd = ( inw ( rtl->ioaddr + Config1 ) & VPDEnable );
00292         if ( vpd ) {
00293                 DBGC ( rtl, "rtl8139 %p EEPROM in use for VPD; cannot use "
00294                        "for options\n", rtl );
00295         } else {
00296                 nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, rtl_nvo_fragments,
00297                            &netdev->refcnt );
00298         }
00299 }
00300 
00301 /**
00302  * Reset NIC
00303  *
00304  * @v netdev            Net device
00305  *
00306  * Issues a hardware reset and waits for the reset to complete.
00307  */
00308 static void rtl_reset ( struct net_device *netdev ) {
00309         struct rtl8139_nic *rtl = netdev->priv;
00310 
00311         /* Reset chip */
00312         outb ( CmdReset, rtl->ioaddr + ChipCmd );
00313         mdelay ( 10 );
00314         memset ( &rtl->tx, 0, sizeof ( rtl->tx ) );
00315         rtl->rx.offset = 0;
00316 }
00317 
00318 /**
00319  * Open NIC
00320  *
00321  * @v netdev            Net device
00322  * @ret rc              Return status code
00323  */
00324 static int rtl_open ( struct net_device *netdev ) {
00325         struct rtl8139_nic *rtl = netdev->priv;
00326         int i;
00327 
00328         /* Program the MAC address */
00329         for ( i = 0 ; i < ETH_ALEN ; i++ )
00330                 outb ( netdev->ll_addr[i], rtl->ioaddr + MAC0 + i );
00331 
00332         /* Set up RX ring */
00333         rtl->rx.ring = malloc ( RX_BUF_LEN + RX_BUF_PAD );
00334         if ( ! rtl->rx.ring )
00335                 return -ENOMEM;
00336         outl ( virt_to_bus ( rtl->rx.ring ), rtl->ioaddr + RxBuf );
00337         DBGC ( rtl, "rtl8139 %p RX ring at %lx\n",
00338                rtl, virt_to_bus ( rtl->rx.ring ) );
00339 
00340         /* Enable TX and RX */
00341         outb ( ( CmdRxEnb | CmdTxEnb ), rtl->ioaddr + ChipCmd );
00342         outl ( ( ( RX_FIFO_THRESH << 13 ) | ( RX_BUF_LEN_IDX << 11 ) |
00343                  ( RX_DMA_BURST << 8 ) | AcceptBroadcast | AcceptMulticast |
00344                  AcceptMyPhys ), rtl->ioaddr + RxConfig );
00345         outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 0 );
00346         outl ( 0xffffffffUL, rtl->ioaddr + MAR0 + 4 );
00347         outl ( ( ( TX_DMA_BURST << 8 ) | ( TX_IPG << 24 ) ),
00348                rtl->ioaddr + TxConfig );
00349 
00350         return 0;
00351 }
00352 
00353 /**
00354  * Close NIC
00355  *
00356  * @v netdev            Net device
00357  */
00358 static void rtl_close ( struct net_device *netdev ) {
00359         struct rtl8139_nic *rtl = netdev->priv;
00360 
00361         /* Reset the hardware to disable everything in one go */
00362         rtl_reset ( netdev );
00363 
00364         /* Free RX ring */
00365         free ( rtl->rx.ring );
00366         rtl->rx.ring = NULL;
00367 }
00368 
00369 /** 
00370  * Transmit packet
00371  *
00372  * @v netdev    Network device
00373  * @v iobuf     I/O buffer
00374  * @ret rc      Return status code
00375  */
00376 static int rtl_transmit ( struct net_device *netdev,
00377                           struct io_buffer *iobuf ) {
00378         struct rtl8139_nic *rtl = netdev->priv;
00379 
00380         /* Check for space in TX ring */
00381         if ( rtl->tx.iobuf[rtl->tx.next] != NULL ) {
00382                 DBGC ( rtl, "rtl8139 %p TX overflow\n", rtl );
00383                 return -ENOBUFS;
00384         }
00385 
00386         /* Pad and align packet */
00387         iob_pad ( iobuf, ETH_ZLEN );
00388 
00389         /* Add to TX ring */
00390         DBGC2 ( rtl, "rtl8139 %p TX id %d at %lx+%zx\n", rtl, rtl->tx.next,
00391                 virt_to_bus ( iobuf->data ), iob_len ( iobuf ) );
00392         rtl->tx.iobuf[rtl->tx.next] = iobuf;
00393         outl ( virt_to_bus ( iobuf->data ),
00394                rtl->ioaddr + TxAddr0 + 4 * rtl->tx.next );
00395         outl ( ( ( ( TX_FIFO_THRESH & 0x7e0 ) << 11 ) | iob_len ( iobuf ) ),
00396                rtl->ioaddr + TxStatus0 + 4 * rtl->tx.next );
00397         rtl->tx.next = ( rtl->tx.next + 1 ) % TX_RING_SIZE;
00398 
00399         return 0;
00400 }
00401 
00402 /**
00403  * Poll for received packets
00404  *
00405  * @v netdev    Network device
00406  */
00407 static void rtl_poll ( struct net_device *netdev ) {
00408         struct rtl8139_nic *rtl = netdev->priv;
00409         unsigned int status;
00410         unsigned int tsad;
00411         unsigned int rx_status;
00412         unsigned int rx_len;
00413         struct io_buffer *rx_iob;
00414         int wrapped_len;
00415         int i;
00416 
00417         /* Acknowledge interrupts */
00418         status = inw ( rtl->ioaddr + IntrStatus );
00419         if ( ! status )
00420                 return;
00421         outw ( status, rtl->ioaddr + IntrStatus );
00422 
00423         /* Handle TX completions */
00424         tsad = inw ( rtl->ioaddr + TxSummary );
00425         for ( i = 0 ; i < TX_RING_SIZE ; i++ ) {
00426                 if ( ( rtl->tx.iobuf[i] != NULL ) && ( tsad & ( 1 << i ) ) ) {
00427                         DBGC2 ( rtl, "rtl8139 %p TX id %d complete\n",
00428                                 rtl, i );
00429                         netdev_tx_complete ( netdev, rtl->tx.iobuf[i] );
00430                         rtl->tx.iobuf[i] = NULL;
00431                 }
00432         }
00433 
00434         /* Handle received packets */
00435         while ( ! ( inw ( rtl->ioaddr + ChipCmd ) & RxBufEmpty ) ) {
00436                 rx_status = * ( ( uint16_t * )
00437                                 ( rtl->rx.ring + rtl->rx.offset ) );
00438                 rx_len = * ( ( uint16_t * )
00439                              ( rtl->rx.ring + rtl->rx.offset + 2 ) );
00440                 if ( rx_status & RxOK ) {
00441                         DBGC2 ( rtl, "rtl8139 %p RX packet at offset "
00442                                 "%x+%x\n", rtl, rtl->rx.offset, rx_len );
00443 
00444                         rx_iob = alloc_iob ( rx_len );
00445                         if ( ! rx_iob ) {
00446                                 netdev_rx_err ( netdev, NULL, -ENOMEM );
00447                                 /* Leave packet for next call to poll() */
00448                                 break;
00449                         }
00450 
00451                         wrapped_len = ( ( rtl->rx.offset + 4 + rx_len )
00452                                         - RX_BUF_LEN );
00453                         if ( wrapped_len < 0 )
00454                                 wrapped_len = 0;
00455 
00456                         memcpy ( iob_put ( rx_iob, rx_len - wrapped_len ),
00457                                  rtl->rx.ring + rtl->rx.offset + 4,
00458                                  rx_len - wrapped_len );
00459                         memcpy ( iob_put ( rx_iob, wrapped_len ),
00460                                  rtl->rx.ring, wrapped_len );
00461 
00462                         netdev_rx ( netdev, rx_iob );
00463                 } else {
00464                         DBGC ( rtl, "rtl8139 %p RX bad packet (status %#04x "
00465                                "len %d)\n", rtl, rx_status, rx_len );
00466                         netdev_rx_err ( netdev, NULL, -EINVAL );
00467                 }
00468                 rtl->rx.offset = ( ( ( rtl->rx.offset + 4 + rx_len + 3 ) & ~3 )
00469                                    % RX_BUF_LEN );
00470                 outw ( rtl->rx.offset - 16, rtl->ioaddr + RxBufPtr );
00471         }
00472 }
00473 
00474 /**
00475  * Enable/disable interrupts
00476  *
00477  * @v netdev    Network device
00478  * @v enable    Interrupts should be enabled
00479  */
00480 static void rtl_irq ( struct net_device *netdev, int enable ) {
00481         struct rtl8139_nic *rtl = netdev->priv;
00482 
00483         DBGC ( rtl, "rtl8139 %p interrupts %s\n",
00484                rtl, ( enable ? "enabled" : "disabled" ) );
00485         outw ( ( enable ? ( ROK | RER | TOK | TER ) : 0 ),
00486                rtl->ioaddr + IntrMask );
00487 }
00488 
00489 /** RTL8139 net device operations */
00490 static struct net_device_operations rtl_operations = {
00491         .open           = rtl_open,
00492         .close          = rtl_close,
00493         .transmit       = rtl_transmit,
00494         .poll           = rtl_poll,
00495         .irq            = rtl_irq,
00496 };
00497 
00498 /**
00499  * Probe PCI device
00500  *
00501  * @v pci       PCI device
00502  * @v id        PCI ID
00503  * @ret rc      Return status code
00504  */
00505 static int rtl_probe ( struct pci_device *pci,
00506                        const struct pci_device_id *id __unused ) {
00507         struct net_device *netdev;
00508         struct rtl8139_nic *rtl;
00509         int rc;
00510 
00511         /* Allocate net device */
00512         netdev = alloc_etherdev ( sizeof ( *rtl ) );
00513         if ( ! netdev )
00514                 return -ENOMEM;
00515         netdev_init ( netdev, &rtl_operations );
00516         rtl = netdev->priv;
00517         pci_set_drvdata ( pci, netdev );
00518         netdev->dev = &pci->dev;
00519         memset ( rtl, 0, sizeof ( *rtl ) );
00520         rtl->ioaddr = pci->ioaddr;
00521 
00522         /* Fix up PCI device */
00523         adjust_pci_device ( pci );
00524 
00525         /* Reset the NIC, set up EEPROM access and read MAC address */
00526         rtl_reset ( netdev );
00527         rtl_init_eeprom ( netdev );
00528         nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->hw_addr, ETH_ALEN );
00529 
00530         /* Mark as link up; we don't yet handle link state */
00531         netdev_link_up ( netdev );
00532         
00533         /* Register network device */
00534         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00535                 goto err_register_netdev;
00536 
00537         /* Register non-volatile storage */
00538         if ( rtl->nvo.nvs ) {
00539                 if ( ( rc = register_nvo ( &rtl->nvo,
00540                                            netdev_settings ( netdev ) ) ) != 0)
00541                         goto err_register_nvo;
00542         }
00543 
00544         return 0;
00545 
00546  err_register_nvo:
00547         unregister_netdev ( netdev );
00548  err_register_netdev:
00549         rtl_reset ( netdev );
00550         netdev_nullify ( netdev );
00551         netdev_put ( netdev );
00552         return rc;
00553 }
00554 
00555 /**
00556  * Remove PCI device
00557  *
00558  * @v pci       PCI device
00559  */
00560 static void rtl_remove ( struct pci_device *pci ) {
00561         struct net_device *netdev = pci_get_drvdata ( pci );
00562         struct rtl8139_nic *rtl = netdev->priv;
00563 
00564         if ( rtl->nvo.nvs )
00565                 unregister_nvo ( &rtl->nvo );
00566         unregister_netdev ( netdev );
00567         rtl_reset ( netdev );
00568         netdev_nullify ( netdev );
00569         netdev_put ( netdev );
00570 }
00571 
00572 static struct pci_device_id rtl8139_nics[] = {
00573 PCI_ROM(0x10ec, 0x8129, "rtl8129",       "Realtek 8129", 0),
00574 PCI_ROM(0x10ec, 0x8139, "rtl8139",       "Realtek 8139", 0),
00575 PCI_ROM(0x10ec, 0x8138, "rtl8139b",      "Realtek 8139B", 0),
00576 PCI_ROM(0x1186, 0x1300, "dfe538",        "DFE530TX+/DFE538TX", 0),
00577 PCI_ROM(0x1113, 0x1211, "smc1211-1",     "SMC EZ10/100", 0),
00578 PCI_ROM(0x1112, 0x1211, "smc1211",       "SMC EZ10/100", 0),
00579 PCI_ROM(0x1500, 0x1360, "delta8139",     "Delta Electronics 8139", 0),
00580 PCI_ROM(0x4033, 0x1360, "addtron8139",   "Addtron Technology 8139", 0),
00581 PCI_ROM(0x1186, 0x1340, "dfe690txd",     "D-Link DFE690TXD", 0),
00582 PCI_ROM(0x13d1, 0xab06, "fe2000vx",      "AboCom FE2000VX", 0),
00583 PCI_ROM(0x1259, 0xa117, "allied8139",    "Allied Telesyn 8139", 0),
00584 PCI_ROM(0x14ea, 0xab06, "fnw3603tx",     "Planex FNW-3603-TX", 0),
00585 PCI_ROM(0x14ea, 0xab07, "fnw3800tx",     "Planex FNW-3800-TX", 0),
00586 PCI_ROM(0xffff, 0x8139, "clone-rtl8139", "Cloned 8139", 0),
00587 };
00588 
00589 struct pci_driver rtl8139_driver __pci_driver = {
00590         .ids = rtl8139_nics,
00591         .id_count = ( sizeof ( rtl8139_nics ) / sizeof ( rtl8139_nics[0] ) ),
00592         .probe = rtl_probe,
00593         .remove = rtl_remove,
00594 };

Generated on Tue Apr 6 20:01:02 2010 for gPXE by  doxygen 1.5.7.1