iPXE
myson.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdint.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <errno.h>
00030 #include <byteswap.h>
00031 #include <ipxe/netdevice.h>
00032 #include <ipxe/ethernet.h>
00033 #include <ipxe/if_ether.h>
00034 #include <ipxe/iobuf.h>
00035 #include <ipxe/malloc.h>
00036 #include <ipxe/pci.h>
00037 #include <ipxe/mii.h>
00038 #include "myson.h"
00039 
00040 /** @file
00041  *
00042  * Myson Technology network card driver
00043  *
00044  */
00045 
00046 /******************************************************************************
00047  *
00048  * Device reset
00049  *
00050  ******************************************************************************
00051  */
00052 
00053 /**
00054  * Reset controller chip
00055  *
00056  * @v myson             Myson device
00057  * @ret rc              Return status code
00058  */
00059 static int myson_soft_reset ( struct myson_nic *myson ) {
00060         uint32_t bcr;
00061         unsigned int i;
00062 
00063         /* Initiate reset */
00064         bcr = readl ( myson->regs + MYSON_BCR );
00065         writel ( ( bcr | MYSON_BCR_SWR ), myson->regs + MYSON_BCR );
00066 
00067         /* Wait for reset to complete */
00068         for ( i = 0 ; i < MYSON_RESET_MAX_WAIT_MS ; i++ ) {
00069 
00070                 /* If reset is not complete, delay 1ms and retry */
00071                 if ( readl ( myson->regs + MYSON_BCR ) & MYSON_BCR_SWR ) {
00072                         mdelay ( 1 );
00073                         continue;
00074                 }
00075 
00076                 /* Apply a sensible default bus configuration */
00077                 bcr = readl ( myson->regs + MYSON_BCR );
00078                 bcr &= ~MYSON_BCR_PBL_MASK;
00079                 bcr |= ( MYSON_BCR_RLE | MYSON_BCR_RME | MYSON_BCR_WIE |
00080                          MYSON_BCR_PBL_DEFAULT );
00081                 writel ( bcr, myson->regs + MYSON_BCR );
00082                 DBGC ( myson, "MYSON %p using configuration %08x\n",
00083                        myson, bcr );
00084 
00085                 return 0;
00086         }
00087 
00088         DBGC ( myson, "MYSON %p timed out waiting for reset\n", myson );
00089         return -ETIMEDOUT;
00090 }
00091 
00092 /**
00093  * Reload configuration from EEPROM
00094  *
00095  * @v myson             Myson device
00096  * @ret rc              Return status code
00097  */
00098 static int myson_reload_config ( struct myson_nic *myson ) {
00099         unsigned int i;
00100 
00101         /* Initiate reload */
00102         writel ( MYSON_ROM_AUTOLD, myson->regs + MYSON_ROM_MII );
00103 
00104         /* Wait for reload to complete */
00105         for ( i = 0 ; i < MYSON_AUTOLD_MAX_WAIT_MS ; i++ ) {
00106 
00107                 /* If reload is not complete, delay 1ms and retry */
00108                 if ( readl ( myson->regs + MYSON_ROM_MII ) & MYSON_ROM_AUTOLD ){
00109                         mdelay ( 1 );
00110                         continue;
00111                 }
00112 
00113                 return 0;
00114         }
00115 
00116         DBGC ( myson, "MYSON %p timed out waiting for configuration "
00117                "reload\n", myson );
00118         return -ETIMEDOUT;
00119 }
00120 
00121 /**
00122  * Reset hardware
00123  *
00124  * @v myson             Myson device
00125  * @ret rc              Return status code
00126  */
00127 static int myson_reset ( struct myson_nic *myson ) {
00128         int rc;
00129 
00130         /* Disable all interrupts */
00131         writel ( 0, myson->regs + MYSON_IMR );
00132 
00133         /* Perform soft reset */
00134         if ( ( rc = myson_soft_reset ( myson ) ) != 0 )
00135                 return rc;
00136 
00137         /* Reload configuration from EEPROM */
00138         if ( ( rc = myson_reload_config ( myson ) ) != 0 )
00139                 return rc;
00140 
00141         return 0;
00142 }
00143 
00144 /******************************************************************************
00145  *
00146  * Network device interface
00147  *
00148  ******************************************************************************
00149  */
00150 
00151 /**
00152  * Create descriptor ring
00153  *
00154  * @v myson             Myson device
00155  * @v ring              Descriptor ring
00156  * @ret rc              Return status code
00157  */
00158 static int myson_create_ring ( struct myson_nic *myson,
00159                                struct myson_ring *ring ) {
00160         size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
00161         struct myson_descriptor *desc;
00162         struct myson_descriptor *next;
00163         physaddr_t address;
00164         unsigned int i;
00165         int rc;
00166 
00167         /* Allocate descriptor ring */
00168         ring->desc = malloc_dma ( len, MYSON_RING_ALIGN );
00169         if ( ! ring->desc ) {
00170                 rc = -ENOMEM;
00171                 goto err_alloc;
00172         }
00173         address = virt_to_bus ( ring->desc );
00174 
00175         /* Check address is usable by card */
00176         if ( ! myson_address_ok ( address + len ) ) {
00177                 DBGC ( myson, "MYSON %p cannot support 64-bit ring address\n",
00178                        myson );
00179                 rc = -ENOTSUP;
00180                 goto err_64bit;
00181         }
00182 
00183         /* Initialise descriptor ring */
00184         memset ( ring->desc, 0, len );
00185         for ( i = 0 ; i < ring->count ; i++ ) {
00186                 desc = &ring->desc[i];
00187                 next = &ring->desc[ ( i + 1 ) % ring->count ];
00188                 desc->next = cpu_to_le32 ( virt_to_bus ( next ) );
00189         }
00190 
00191         /* Program ring address */
00192         writel ( address, myson->regs + ring->reg );
00193         DBGC ( myson, "MYSON %p ring %02x is at [%08llx,%08llx)\n",
00194                myson, ring->reg, ( ( unsigned long long ) address ),
00195                ( ( unsigned long long ) address + len ) );
00196 
00197         return 0;
00198 
00199  err_64bit:
00200         free_dma ( ring->desc, len );
00201         ring->desc = NULL;
00202  err_alloc:
00203         return rc;
00204 }
00205 
00206 /**
00207  * Destroy descriptor ring
00208  *
00209  * @v myson             Myson device
00210  * @v ring              Descriptor ring
00211  */
00212 static void myson_destroy_ring ( struct myson_nic *myson,
00213                                  struct myson_ring *ring ) {
00214         size_t len = ( ring->count * sizeof ( ring->desc[0] ) );
00215 
00216         /* Clear ring address */
00217         writel ( 0, myson->regs + ring->reg );
00218 
00219         /* Free descriptor ring */
00220         free_dma ( ring->desc, len );
00221         ring->desc = NULL;
00222         ring->prod = 0;
00223         ring->cons = 0;
00224 }
00225 
00226 /**
00227  * Refill receive descriptor ring
00228  *
00229  * @v netdev            Network device
00230  */
00231 static void myson_refill_rx ( struct net_device *netdev ) {
00232         struct myson_nic *myson = netdev->priv;
00233         struct myson_descriptor *rx;
00234         struct io_buffer *iobuf;
00235         unsigned int rx_idx;
00236         physaddr_t address;
00237 
00238         while ( ( myson->rx.prod - myson->rx.cons ) < MYSON_NUM_RX_DESC ) {
00239 
00240                 /* Allocate I/O buffer */
00241                 iobuf = alloc_iob ( MYSON_RX_MAX_LEN );
00242                 if ( ! iobuf ) {
00243                         /* Wait for next refill */
00244                         return;
00245                 }
00246 
00247                 /* Check address is usable by card */
00248                 address = virt_to_bus ( iobuf->data );
00249                 if ( ! myson_address_ok ( address ) ) {
00250                         DBGC ( myson, "MYSON %p cannot support 64-bit RX "
00251                                "buffer address\n", myson );
00252                         netdev_rx_err ( netdev, iobuf, -ENOTSUP );
00253                         return;
00254                 }
00255 
00256                 /* Get next receive descriptor */
00257                 rx_idx = ( myson->rx.prod++ % MYSON_NUM_RX_DESC );
00258                 rx = &myson->rx.desc[rx_idx];
00259 
00260                 /* Populate receive descriptor */
00261                 rx->address = cpu_to_le32 ( address );
00262                 rx->control =
00263                         cpu_to_le32 ( MYSON_RX_CTRL_RBS ( MYSON_RX_MAX_LEN ) );
00264                 wmb();
00265                 rx->status = cpu_to_le32 ( MYSON_RX_STAT_OWN );
00266                 wmb();
00267 
00268                 /* Record I/O buffer */
00269                 assert ( myson->rx_iobuf[rx_idx] == NULL );
00270                 myson->rx_iobuf[rx_idx] = iobuf;
00271 
00272                 /* Notify card that there are descriptors available */
00273                 writel ( 0, myson->regs + MYSON_RXPDR );
00274 
00275                 DBGC2 ( myson, "MYSON %p RX %d is [%llx,%llx)\n", myson,
00276                         rx_idx, ( ( unsigned long long ) address ),
00277                         ( ( unsigned long long ) address + MYSON_RX_MAX_LEN ) );
00278         }
00279 }
00280 
00281 /**
00282  * Open network device
00283  *
00284  * @v netdev            Network device
00285  * @ret rc              Return status code
00286  */
00287 static int myson_open ( struct net_device *netdev ) {
00288         struct myson_nic *myson = netdev->priv;
00289         union myson_physical_address mac;
00290         int rc;
00291 
00292         /* Set MAC address */
00293         memset ( &mac, 0, sizeof ( mac ) );
00294         memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
00295         writel ( le32_to_cpu ( mac.reg.low ), myson->regs + MYSON_PAR0 );
00296         writel ( le32_to_cpu ( mac.reg.high ), myson->regs + MYSON_PAR4 );
00297 
00298         /* Create transmit descriptor ring */
00299         if ( ( rc = myson_create_ring ( myson, &myson->tx ) ) != 0 )
00300                 goto err_create_tx;
00301 
00302         /* Create receive descriptor ring */
00303         if ( ( rc = myson_create_ring ( myson, &myson->rx ) ) != 0 )
00304                 goto err_create_rx;
00305 
00306         /* Configure transmitter and receiver */
00307         writel ( ( MYSON_TCR_TE | MYSON_RCR_PROM | MYSON_RCR_AB | MYSON_RCR_AM |
00308                    MYSON_RCR_ARP | MYSON_RCR_ALP | MYSON_RCR_RE ),
00309                  myson->regs + MYSON_TCR_RCR );
00310 
00311         /* Fill receive ring */
00312         myson_refill_rx ( netdev );
00313 
00314         return 0;
00315 
00316         myson_destroy_ring ( myson, &myson->rx );
00317  err_create_rx:
00318         myson_destroy_ring ( myson, &myson->tx );
00319  err_create_tx:
00320         return rc;
00321 }
00322 
00323 /**
00324  * Wait for transmit and receive to become idle
00325  *
00326  * @v myson             Myson device
00327  * @ret rc              Return status code
00328  */
00329 static int myson_wait_idle ( struct myson_nic *myson ) {
00330         uint32_t tcr_rcr;
00331         unsigned int i;
00332 
00333         /* Wait for both transmit and receive to be idle */
00334         for ( i = 0 ; i < MYSON_IDLE_MAX_WAIT_MS ; i++ ) {
00335 
00336                 /* If either process is running, delay 1ms and retry */
00337                 tcr_rcr = readl ( myson->regs + MYSON_TCR_RCR );
00338                 if ( tcr_rcr & ( MYSON_TCR_TXS | MYSON_RCR_RXS ) ) {
00339                         mdelay ( 1 );
00340                         continue;
00341                 }
00342 
00343                 return 0;
00344         }
00345 
00346         DBGC ( myson, "MYSON %p timed out waiting for idle state (status "
00347                "%08x)\n", myson, tcr_rcr );
00348         return -ETIMEDOUT;
00349 }
00350 
00351 /**
00352  * Close network device
00353  *
00354  * @v netdev            Network device
00355  */
00356 static void myson_close ( struct net_device *netdev ) {
00357         struct myson_nic *myson = netdev->priv;
00358         unsigned int i;
00359 
00360         /* Disable receiver and transmitter */
00361         writel ( 0, myson->regs + MYSON_TCR_RCR );
00362 
00363         /* Allow time for receiver and transmitter to become idle */
00364         myson_wait_idle ( myson );
00365 
00366         /* Destroy receive descriptor ring */
00367         myson_destroy_ring ( myson, &myson->rx );
00368 
00369         /* Discard any unused receive buffers */
00370         for ( i = 0 ; i < MYSON_NUM_RX_DESC ; i++ ) {
00371                 if ( myson->rx_iobuf[i] )
00372                         free_iob ( myson->rx_iobuf[i] );
00373                 myson->rx_iobuf[i] = NULL;
00374         }
00375 
00376         /* Destroy transmit descriptor ring */
00377         myson_destroy_ring ( myson, &myson->tx );
00378 }
00379 
00380 /**
00381  * Transmit packet
00382  *
00383  * @v netdev            Network device
00384  * @v iobuf             I/O buffer
00385  * @ret rc              Return status code
00386  */
00387 static int myson_transmit ( struct net_device *netdev,
00388                             struct io_buffer *iobuf ) {
00389         struct myson_nic *myson = netdev->priv;
00390         struct myson_descriptor *tx;
00391         unsigned int tx_idx;
00392         physaddr_t address;
00393 
00394         /* Check address is usable by card */
00395         address = virt_to_bus ( iobuf->data );
00396         if ( ! myson_address_ok ( address ) ) {
00397                 DBGC ( myson, "MYSON %p cannot support 64-bit TX buffer "
00398                        "address\n", myson );
00399                 return -ENOTSUP;
00400         }
00401 
00402         /* Get next transmit descriptor */
00403         if ( ( myson->tx.prod - myson->tx.cons ) >= MYSON_NUM_TX_DESC ) {
00404                 DBGC ( myson, "MYSON %p out of transmit descriptors\n",
00405                        myson );
00406                 return -ENOBUFS;
00407         }
00408         tx_idx = ( myson->tx.prod++ % MYSON_NUM_TX_DESC );
00409         tx = &myson->tx.desc[tx_idx];
00410 
00411         /* Populate transmit descriptor */
00412         tx->address = cpu_to_le32 ( address );
00413         tx->control = cpu_to_le32 ( MYSON_TX_CTRL_IC | MYSON_TX_CTRL_LD |
00414                                     MYSON_TX_CTRL_FD | MYSON_TX_CTRL_CRC |
00415                                     MYSON_TX_CTRL_PAD | MYSON_TX_CTRL_RTLC |
00416                                     MYSON_TX_CTRL_PKTS ( iob_len ( iobuf ) ) |
00417                                     MYSON_TX_CTRL_TBS ( iob_len ( iobuf ) ) );
00418         wmb();
00419         tx->status = cpu_to_le32 ( MYSON_TX_STAT_OWN );
00420         wmb();
00421 
00422         /* Notify card that there are packets ready to transmit */
00423         writel ( 0, myson->regs + MYSON_TXPDR );
00424 
00425         DBGC2 ( myson, "MYSON %p TX %d is [%llx,%llx)\n", myson, tx_idx,
00426                 ( ( unsigned long long ) address ),
00427                 ( ( unsigned long long ) address + iob_len ( iobuf ) ) );
00428 
00429         return 0;
00430 }
00431 
00432 /**
00433  * Poll for completed packets
00434  *
00435  * @v netdev            Network device
00436  */
00437 static void myson_poll_tx ( struct net_device *netdev ) {
00438         struct myson_nic *myson = netdev->priv;
00439         struct myson_descriptor *tx;
00440         unsigned int tx_idx;
00441 
00442         /* Check for completed packets */
00443         while ( myson->tx.cons != myson->tx.prod ) {
00444 
00445                 /* Get next transmit descriptor */
00446                 tx_idx = ( myson->tx.cons % MYSON_NUM_TX_DESC );
00447                 tx = &myson->tx.desc[tx_idx];
00448 
00449                 /* Stop if descriptor is still in use */
00450                 if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_OWN ) )
00451                         return;
00452 
00453                 /* Complete TX descriptor */
00454                 if ( tx->status & cpu_to_le32 ( MYSON_TX_STAT_ABORT |
00455                                                 MYSON_TX_STAT_CSL ) ) {
00456                         DBGC ( myson, "MYSON %p TX %d completion error "
00457                                "(%08x)\n", myson, tx_idx,
00458                                le32_to_cpu ( tx->status ) );
00459                         netdev_tx_complete_next_err ( netdev, -EIO );
00460                 } else {
00461                         DBGC2 ( myson, "MYSON %p TX %d complete\n",
00462                                 myson, tx_idx );
00463                         netdev_tx_complete_next ( netdev );
00464                 }
00465                 myson->tx.cons++;
00466         }
00467 }
00468 
00469 /**
00470  * Poll for received packets
00471  *
00472  * @v netdev            Network device
00473  */
00474 static void myson_poll_rx ( struct net_device *netdev ) {
00475         struct myson_nic *myson = netdev->priv;
00476         struct myson_descriptor *rx;
00477         struct io_buffer *iobuf;
00478         unsigned int rx_idx;
00479         size_t len;
00480 
00481         /* Check for received packets */
00482         while ( myson->rx.cons != myson->rx.prod ) {
00483 
00484                 /* Get next receive descriptor */
00485                 rx_idx = ( myson->rx.cons % MYSON_NUM_RX_DESC );
00486                 rx = &myson->rx.desc[rx_idx];
00487 
00488                 /* Stop if descriptor is still in use */
00489                 if ( rx->status & MYSON_RX_STAT_OWN )
00490                         return;
00491 
00492                 /* Populate I/O buffer */
00493                 iobuf = myson->rx_iobuf[rx_idx];
00494                 myson->rx_iobuf[rx_idx] = NULL;
00495                 len = MYSON_RX_STAT_FLNG ( le32_to_cpu ( rx->status ) );
00496                 iob_put ( iobuf, len - 4 /* strip CRC */ );
00497 
00498                 /* Hand off to network stack */
00499                 if ( rx->status & cpu_to_le32 ( MYSON_RX_STAT_ES ) ) {
00500                         DBGC ( myson, "MYSON %p RX %d error (length %zd, "
00501                                "status %08x)\n", myson, rx_idx, len,
00502                                le32_to_cpu ( rx->status ) );
00503                         netdev_rx_err ( netdev, iobuf, -EIO );
00504                 } else {
00505                         DBGC2 ( myson, "MYSON %p RX %d complete (length "
00506                                 "%zd)\n", myson, rx_idx, len );
00507                         netdev_rx ( netdev, iobuf );
00508                 }
00509                 myson->rx.cons++;
00510         }
00511 }
00512 
00513 /**
00514  * Poll for completed and received packets
00515  *
00516  * @v netdev            Network device
00517  */
00518 static void myson_poll ( struct net_device *netdev ) {
00519         struct myson_nic *myson = netdev->priv;
00520         uint32_t isr;
00521         unsigned int i;
00522 
00523         /* Polling the ISR seems to really upset this card; it ends up
00524          * getting no useful PCI transfers done and, for some reason,
00525          * flooding the network with invalid packets.  Work around
00526          * this by introducing deliberate delays between ISR reads.
00527          */
00528         for ( i = 0 ; i < MYSON_ISR_IODELAY_COUNT ; i++ )
00529                 iodelay();
00530 
00531         /* Check for and acknowledge interrupts */
00532         isr = readl ( myson->regs + MYSON_ISR );
00533         if ( ! isr )
00534                 return;
00535         writel ( isr, myson->regs + MYSON_ISR );
00536 
00537         /* Poll for TX completions, if applicable */
00538         if ( isr & MYSON_IRQ_TI )
00539                 myson_poll_tx ( netdev );
00540 
00541         /* Poll for RX completionsm, if applicable */
00542         if ( isr & MYSON_IRQ_RI )
00543                 myson_poll_rx ( netdev );
00544 
00545         /* Refill RX ring */
00546         myson_refill_rx ( netdev );
00547 }
00548 
00549 /**
00550  * Enable or disable interrupts
00551  *
00552  * @v netdev            Network device
00553  * @v enable            Interrupts should be enabled
00554  */
00555 static void myson_irq ( struct net_device *netdev, int enable ) {
00556         struct myson_nic *myson = netdev->priv;
00557         uint32_t imr;
00558 
00559         imr = ( enable ? ( MYSON_IRQ_TI | MYSON_IRQ_RI ) : 0 );
00560         writel ( imr, myson->regs + MYSON_IMR );
00561 }
00562 
00563 /** Myson network device operations */
00564 static struct net_device_operations myson_operations = {
00565         .open           = myson_open,
00566         .close          = myson_close,
00567         .transmit       = myson_transmit,
00568         .poll           = myson_poll,
00569         .irq            = myson_irq,
00570 };
00571 
00572 /******************************************************************************
00573  *
00574  * PCI interface
00575  *
00576  ******************************************************************************
00577  */
00578 
00579 /**
00580  * Probe PCI device
00581  *
00582  * @v pci               PCI device
00583  * @ret rc              Return status code
00584  */
00585 static int myson_probe ( struct pci_device *pci ) {
00586         struct net_device *netdev;
00587         struct myson_nic *myson;
00588         union myson_physical_address mac;
00589         int rc;
00590 
00591         /* Allocate and initialise net device */
00592         netdev = alloc_etherdev ( sizeof ( *myson ) );
00593         if ( ! netdev ) {
00594                 rc = -ENOMEM;
00595                 goto err_alloc;
00596         }
00597         netdev_init ( netdev, &myson_operations );
00598         myson = netdev->priv;
00599         pci_set_drvdata ( pci, netdev );
00600         netdev->dev = &pci->dev;
00601         memset ( myson, 0, sizeof ( *myson ) );
00602         myson_init_ring ( &myson->tx, MYSON_NUM_TX_DESC, MYSON_TXLBA );
00603         myson_init_ring ( &myson->rx, MYSON_NUM_RX_DESC, MYSON_RXLBA );
00604 
00605         /* Fix up PCI device */
00606         adjust_pci_device ( pci );
00607 
00608         /* Map registers */
00609         myson->regs = ioremap ( pci->membase, MYSON_BAR_SIZE );
00610         if ( ! myson->regs ) {
00611                 rc = -ENODEV;
00612                 goto err_ioremap;
00613         }
00614 
00615         /* Reset the NIC */
00616         if ( ( rc = myson_reset ( myson ) ) != 0 )
00617                 goto err_reset;
00618 
00619         /* Read MAC address */
00620         mac.reg.low = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR0 ) );
00621         mac.reg.high = cpu_to_le32 ( readl ( myson->regs + MYSON_PAR4 ) );
00622         memcpy ( netdev->hw_addr, mac.raw, ETH_ALEN );
00623 
00624         /* Register network device */
00625         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00626                 goto err_register_netdev;
00627 
00628         /* Mark as link up; we don't yet handle link state */
00629         netdev_link_up ( netdev );
00630 
00631         return 0;
00632 
00633         unregister_netdev ( netdev );
00634  err_register_netdev:
00635         myson_reset ( myson );
00636  err_reset:
00637         iounmap ( myson->regs );
00638  err_ioremap:
00639         netdev_nullify ( netdev );
00640         netdev_put ( netdev );
00641  err_alloc:
00642         return rc;
00643 }
00644 
00645 /**
00646  * Remove PCI device
00647  *
00648  * @v pci               PCI device
00649  */
00650 static void myson_remove ( struct pci_device *pci ) {
00651         struct net_device *netdev = pci_get_drvdata ( pci );
00652         struct myson_nic *myson = netdev->priv;
00653 
00654         /* Unregister network device */
00655         unregister_netdev ( netdev );
00656 
00657         /* Reset card */
00658         myson_reset ( myson );
00659 
00660         /* Free network device */
00661         iounmap ( myson->regs );
00662         netdev_nullify ( netdev );
00663         netdev_put ( netdev );
00664 }
00665 
00666 /** Myson PCI device IDs */
00667 static struct pci_device_id myson_nics[] = {
00668         PCI_ROM ( 0x1516, 0x0800, "mtd800", "MTD-8xx", 0 ),
00669         PCI_ROM ( 0x1516, 0x0803, "mtd803", "Surecom EP-320X-S", 0 ),
00670         PCI_ROM ( 0x1516, 0x0891, "mtd891", "MTD-8xx", 0 ),
00671 };
00672 
00673 /** Myson PCI driver */
00674 struct pci_driver myson_driver __pci_driver = {
00675         .ids = myson_nics,
00676         .id_count = ( sizeof ( myson_nics ) / sizeof ( myson_nics[0] ) ),
00677         .probe = myson_probe,
00678         .remove = myson_remove,
00679 };