iPXE
icplus.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2018 Sylvie Barlow <sylvie.c.barlow@gmail.com>.
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 "icplus.h"
00038 
00039 /** @file
00040  *
00041  * IC+ network driver
00042  *
00043  */
00044 
00045 /******************************************************************************
00046  *
00047  * Device reset
00048  *
00049  ******************************************************************************
00050  */
00051 
00052 /**
00053  * Reset hardware
00054  *
00055  * @v icp               IC+ device
00056  * @ret rc              Return status code
00057  */
00058 static int icplus_reset ( struct icplus_nic *icp ) {
00059         uint32_t asicctrl;
00060         unsigned int i;
00061 
00062         /* Trigger reset */
00063         writel ( ( ICP_ASICCTRL_GLOBALRESET | ICP_ASICCTRL_DMA |
00064                    ICP_ASICCTRL_FIFO | ICP_ASICCTRL_NETWORK | ICP_ASICCTRL_HOST |
00065                    ICP_ASICCTRL_AUTOINIT ), ( icp->regs + ICP_ASICCTRL ) );
00066 
00067         /* Wait for reset to complete */
00068         for ( i = 0 ; i < ICP_RESET_MAX_WAIT_MS ; i++ ) {
00069 
00070                 /* Check if device is ready */
00071                 asicctrl = readl ( icp->regs + ICP_ASICCTRL );
00072                 if ( ! ( asicctrl & ICP_ASICCTRL_RESETBUSY ) )
00073                         return 0;
00074 
00075                 /* Delay */
00076                 mdelay ( 1 );
00077         }
00078 
00079         DBGC ( icp, "ICPLUS %p timed out waiting for reset (asicctrl %#08x)\n",
00080                icp, asicctrl );
00081         return -ETIMEDOUT;
00082 }
00083 
00084 /******************************************************************************
00085  *
00086  * EEPROM interface
00087  *
00088  ******************************************************************************
00089  */
00090 
00091 /**
00092  * Read data from EEPROM
00093  *
00094  * @v nvs               NVS device
00095  * @v address           Address from which to read
00096  * @v data              Data buffer
00097  * @v len               Length of data buffer
00098  * @ret rc              Return status code
00099  */
00100 static int icplus_read_eeprom ( struct nvs_device *nvs, unsigned int address,
00101                                 void *data, size_t len ) {
00102         struct icplus_nic *icp =
00103                 container_of ( nvs, struct icplus_nic, eeprom );
00104         unsigned int i;
00105         uint16_t eepromctrl;
00106         uint16_t *data_word = data;
00107 
00108         /* Sanity check.  We advertise a blocksize of one word, so
00109          * should only ever receive single-word requests.
00110          */
00111         assert ( len == sizeof ( *data_word ) );
00112 
00113         /* Initiate read */
00114         writew ( ( ICP_EEPROMCTRL_OPCODE_READ |
00115                    ICP_EEPROMCTRL_ADDRESS ( address ) ),
00116                  ( icp->regs + ICP_EEPROMCTRL ) );
00117 
00118         /* Wait for read to complete */
00119         for ( i = 0 ; i < ICP_EEPROM_MAX_WAIT_MS ; i++ ) {
00120 
00121                 /* If read is not complete, delay 1ms and retry */
00122                 eepromctrl = readw ( icp->regs + ICP_EEPROMCTRL );
00123                 if ( eepromctrl & ICP_EEPROMCTRL_BUSY ) {
00124                         mdelay ( 1 );
00125                         continue;
00126                 }
00127 
00128                 /* Extract data */
00129                 *data_word = cpu_to_le16 ( readw ( icp->regs + ICP_EEPROMDATA ));
00130                 return 0;
00131         }
00132 
00133         DBGC ( icp, "ICPLUS %p timed out waiting for EEPROM read\n", icp );
00134         return -ETIMEDOUT;
00135 }
00136 
00137 /**
00138  * Write data to EEPROM
00139  *
00140  * @v nvs               NVS device
00141  * @v address           Address to which to write
00142  * @v data              Data buffer
00143  * @v len               Length of data buffer
00144  * @ret rc              Return status code
00145  */
00146 static int icplus_write_eeprom ( struct nvs_device *nvs,
00147                                  unsigned int address __unused,
00148                                  const void *data __unused,
00149                                  size_t len __unused ) {
00150         struct icplus_nic *icp =
00151                 container_of ( nvs, struct icplus_nic, eeprom );
00152 
00153         DBGC ( icp, "ICPLUS %p EEPROM write not supported\n", icp );
00154         return -ENOTSUP;
00155 }
00156 
00157 /**
00158  * Initialise EEPROM
00159  *
00160  * @v icp               IC+ device
00161  */
00162 static void icplus_init_eeprom ( struct icplus_nic *icp ) {
00163 
00164         /* The hardware supports only single-word reads */
00165         icp->eeprom.word_len_log2 = ICP_EEPROM_WORD_LEN_LOG2;
00166         icp->eeprom.size = ICP_EEPROM_MIN_SIZE_WORDS;
00167         icp->eeprom.block_size = 1;
00168         icp->eeprom.read = icplus_read_eeprom;
00169         icp->eeprom.write = icplus_write_eeprom;
00170 }
00171 
00172 /******************************************************************************
00173  *
00174  * MII interface
00175  *
00176  ******************************************************************************
00177  */
00178 
00179 /** Pin mapping for MII bit-bashing interface */
00180 static const uint8_t icplus_mii_bits[] = {
00181         [MII_BIT_MDC]   = ICP_PHYCTRL_MGMTCLK,
00182         [MII_BIT_MDIO]  = ICP_PHYCTRL_MGMTDATA,
00183         [MII_BIT_DRIVE] = ICP_PHYCTRL_MGMTDIR,
00184 };
00185 
00186 /**
00187  * Read input bit
00188  *
00189  * @v basher            Bit-bashing interface
00190  * @v bit_id            Bit number
00191  * @ret zero            Input is a logic 0
00192  * @ret non-zero        Input is a logic 1
00193  */
00194 static int icplus_mii_read_bit ( struct bit_basher *basher,
00195                                  unsigned int bit_id ) {
00196         struct icplus_nic *icp = container_of ( basher, struct icplus_nic,
00197                                                 miibit.basher );
00198         uint8_t mask = icplus_mii_bits[bit_id];
00199         uint8_t reg;
00200 
00201         DBG_DISABLE ( DBGLVL_IO );
00202         reg = readb ( icp->regs + ICP_PHYCTRL );
00203         DBG_ENABLE ( DBGLVL_IO );
00204         return ( reg & mask );
00205 }
00206 
00207 /**
00208  * Set/clear output bit
00209  *
00210  * @v basher            Bit-bashing interface
00211  * @v bit_id            Bit number
00212  * @v data              Value to write
00213  */
00214 static void icplus_mii_write_bit ( struct bit_basher *basher,
00215                                    unsigned int bit_id, unsigned long data ) {
00216         struct icplus_nic *icp = container_of ( basher, struct icplus_nic,
00217                                                 miibit.basher );
00218         uint8_t mask = icplus_mii_bits[bit_id];
00219         uint8_t reg;
00220 
00221         DBG_DISABLE ( DBGLVL_IO );
00222         reg = readb ( icp->regs + ICP_PHYCTRL );
00223         reg &= ~mask;
00224         reg |= ( data & mask );
00225         writeb ( reg, icp->regs + ICP_PHYCTRL );
00226         readb ( icp->regs + ICP_PHYCTRL ); /* Ensure write reaches chip */
00227         DBG_ENABLE ( DBGLVL_IO );
00228 }
00229 
00230 /** MII bit-bashing interface */
00231 static struct bit_basher_operations icplus_basher_ops = {
00232         .read = icplus_mii_read_bit,
00233         .write = icplus_mii_write_bit,
00234 };
00235 
00236 /******************************************************************************
00237  *
00238  * Link state
00239  *
00240  ******************************************************************************
00241  */
00242 
00243 /**
00244  * Configure PHY
00245  *
00246  * @v icp               IC+ device
00247  * @ret rc              Return status code
00248  */
00249 static int icplus_init_phy ( struct icplus_nic *icp ) {
00250         uint32_t asicctrl;
00251         int rc;
00252 
00253         /* Find PHY address */
00254         if ( ( rc = mii_find ( &icp->mii ) ) != 0 ) {
00255                 DBGC ( icp, "ICPLUS %p could not find PHY address: %s\n",
00256                        icp, strerror ( rc ) );
00257                 return rc;
00258         }
00259 
00260         /* Configure PHY to advertise 1000Mbps if applicable */
00261         asicctrl = readl ( icp->regs + ICP_ASICCTRL );
00262         if ( asicctrl & ICP_ASICCTRL_PHYSPEED1000 ) {
00263                 if ( ( rc = mii_write ( &icp->mii, MII_CTRL1000,
00264                                         ADVERTISE_1000FULL ) ) != 0 ) {
00265                         DBGC ( icp, "ICPLUS %p could not advertise 1000Mbps: "
00266                                "%s\n", icp, strerror ( rc ) );
00267                         return rc;
00268                 }
00269         }
00270 
00271         /* Reset PHY */
00272         if ( ( rc = mii_reset ( &icp->mii ) ) != 0 ) {
00273                 DBGC ( icp, "ICPLUS %p could not reset PHY: %s\n",
00274                        icp, strerror ( rc ) );
00275                 return rc;
00276         }
00277 
00278         return 0;
00279 }
00280 
00281 /**
00282  * Check link state
00283  *
00284  * @v netdev            Network device
00285  */
00286 static void icplus_check_link ( struct net_device *netdev ) {
00287         struct icplus_nic *icp = netdev->priv;
00288         uint8_t phyctrl;
00289 
00290         /* Read link status */
00291         phyctrl = readb ( icp->regs + ICP_PHYCTRL );
00292         DBGC ( icp, "ICPLUS %p PHY control is %02x\n", icp, phyctrl );
00293 
00294         /* Update network device */
00295         if ( phyctrl & ICP_PHYCTRL_LINKSPEED ) {
00296                 netdev_link_up ( netdev );
00297         } else {
00298                 netdev_link_down ( netdev );
00299         }
00300 }
00301 
00302 /******************************************************************************
00303  *
00304  * Network device interface
00305  *
00306  ******************************************************************************
00307  */
00308 
00309 /**
00310  * Set descriptor ring base address
00311  *
00312  * @v icp               IC+ device
00313  * @v offset            Register offset
00314  * @v address           Base address
00315  */
00316 static inline void icplus_set_base ( struct icplus_nic *icp, unsigned int offset,
00317                                      void *base ) {
00318         physaddr_t phys = virt_to_bus ( base );
00319 
00320         /* Program base address registers */
00321         writel ( ( phys & 0xffffffffUL ),
00322                  ( icp->regs + offset + ICP_BASE_LO ) );
00323         if ( sizeof ( phys ) > sizeof ( uint32_t ) ) {
00324                 writel ( ( ( ( uint64_t ) phys ) >> 32 ),
00325                          ( icp->regs + offset + ICP_BASE_HI ) );
00326         } else {
00327                 writel ( 0, ( icp->regs + offset + ICP_BASE_HI ) );
00328         }
00329 }
00330 
00331 /**
00332  * Create descriptor ring
00333  *
00334  * @v icp               IC+ device
00335  * @v ring              Descriptor ring
00336  * @ret rc              Return status code
00337  */
00338 static int icplus_create_ring ( struct icplus_nic *icp, struct icplus_ring *ring ) {
00339         size_t len = ( sizeof ( ring->entry[0] ) * ICP_NUM_DESC );
00340         int rc;
00341         unsigned int i;
00342         struct icplus_descriptor *desc;
00343         struct icplus_descriptor *next;
00344 
00345         /* Allocate descriptor ring */
00346         ring->entry = malloc_dma ( len, ICP_ALIGN );
00347         if ( ! ring->entry ) {
00348                 rc = -ENOMEM;
00349                 goto err_alloc;
00350         }
00351 
00352         /* Initialise descriptor ring */
00353         memset ( ring->entry, 0, len );
00354         for ( i = 0 ; i < ICP_NUM_DESC ; i++ ) {
00355                 desc = &ring->entry[i];
00356                 next = &ring->entry[ ( i + 1 ) % ICP_NUM_DESC ];
00357                 desc->next = cpu_to_le64 ( virt_to_bus ( next ) );
00358                 desc->flags = ( ICP_TX_UNALIGN | ICP_TX_INDICATE );
00359                 desc->control = ( ICP_TX_SOLE_FRAG | ICP_DONE );
00360         }
00361 
00362         /* Reset transmit producer & consumer counters */
00363         ring->prod = 0;
00364         ring->cons = 0;
00365 
00366         DBGC ( icp, "ICP %p %s ring at [%#08lx,%#08lx)\n",
00367                icp, ( ( ring->listptr == ICP_TFDLISTPTR ) ? "TX" : "RX" ),
00368                virt_to_bus ( ring->entry ),
00369                ( virt_to_bus ( ring->entry ) + len ) );
00370         return 0;
00371 
00372         free_dma ( ring->entry, len );
00373         ring->entry = NULL;
00374  err_alloc:
00375         return rc;
00376 }
00377 
00378 /**
00379  * Destroy descriptor ring
00380  *
00381  * @v icp               IC+ device
00382  * @v ring              Descriptor ring
00383  */
00384 static void icplus_destroy_ring ( struct icplus_nic *icp __unused,
00385                                   struct icplus_ring *ring ) {
00386         size_t len = ( sizeof ( ring->entry[0] ) * ICP_NUM_DESC );
00387 
00388         /* Free descriptor ring */
00389         free_dma ( ring->entry, len );
00390         ring->entry = NULL;
00391 }
00392 
00393 /**
00394  * Refill receive descriptor ring
00395  *
00396  * @v icp               IC+ device
00397  */
00398 void icplus_refill_rx ( struct icplus_nic *icp ) {
00399         struct icplus_descriptor *desc;
00400         struct io_buffer *iobuf;
00401         unsigned int rx_idx;
00402         physaddr_t address;
00403         unsigned int refilled = 0;
00404 
00405         /* Refill ring */
00406         while ( ( icp->rx.prod - icp->rx.cons ) < ICP_NUM_DESC ) {
00407 
00408                 /* Allocate I/O buffer */
00409                 iobuf = alloc_iob ( ICP_RX_MAX_LEN );
00410                 if ( ! iobuf ) {
00411                         /* Wait for next refill */
00412                         break;
00413                 }
00414 
00415                 /* Get next receive descriptor */
00416                 rx_idx = ( icp->rx.prod++ % ICP_NUM_DESC );
00417                 desc = &icp->rx.entry[rx_idx];
00418 
00419                 /* Populate receive descriptor */
00420                 address = virt_to_bus ( iobuf->data );
00421                 desc->data.address = cpu_to_le64 ( address );
00422                 desc->data.len = cpu_to_le16 ( ICP_RX_MAX_LEN );
00423                 wmb();
00424                 desc->control = 0;
00425 
00426                 /* Record I/O buffer */
00427                 assert ( icp->rx_iobuf[rx_idx] == NULL );
00428                 icp->rx_iobuf[rx_idx] = iobuf;
00429 
00430                 DBGC2 ( icp, "ICP %p RX %d is [%llx,%llx)\n", icp, rx_idx,
00431                         ( ( unsigned long long ) address ),
00432                         ( ( unsigned long long ) address + ICP_RX_MAX_LEN ) );
00433                 refilled++;
00434         }
00435 
00436         /* Push descriptors to card, if applicable */
00437         if ( refilled ) {
00438                 wmb();
00439                 writew ( ICP_DMACTRL_RXPOLLNOW, icp->regs + ICP_DMACTRL );
00440         }
00441 }
00442 
00443 /**
00444  * Open network device
00445  *
00446  * @v netdev            Network device
00447  * @ret rc              Return status code
00448  */
00449 static int icplus_open ( struct net_device *netdev ) {
00450         struct icplus_nic *icp = netdev->priv;
00451         int rc;
00452 
00453         /* Create transmit descriptor ring */
00454         if ( ( rc = icplus_create_ring ( icp, &icp->tx ) ) != 0 )
00455                 goto err_create_tx;
00456 
00457         /* Create receive descriptor ring */
00458         if ( ( rc = icplus_create_ring ( icp, &icp->rx ) ) != 0 )
00459                 goto err_create_rx;
00460 
00461         /* Program descriptor base address */
00462         icplus_set_base ( icp, icp->tx.listptr, icp->tx.entry );
00463         icplus_set_base ( icp, icp->rx.listptr, icp->rx.entry );
00464 
00465         /* Enable receive mode */
00466         writew ( ( ICP_RXMODE_UNICAST | ICP_RXMODE_MULTICAST |
00467                    ICP_RXMODE_BROADCAST | ICP_RXMODE_ALLFRAMES ),
00468                  icp->regs + ICP_RXMODE );
00469 
00470         /* Enable transmitter and receiver */
00471         writel ( ( ICP_MACCTRL_TXENABLE | ICP_MACCTRL_RXENABLE |
00472                    ICP_MACCTRL_DUPLEX ), icp->regs + ICP_MACCTRL );
00473 
00474         /* Fill receive ring */
00475         icplus_refill_rx ( icp );
00476 
00477         /* Check link state */
00478         icplus_check_link ( netdev );
00479 
00480         return 0;
00481 
00482         icplus_reset ( icp );
00483         icplus_destroy_ring ( icp, &icp->rx );
00484  err_create_rx:
00485         icplus_destroy_ring ( icp, &icp->tx );
00486  err_create_tx:
00487         return rc;
00488 }
00489 
00490 /**
00491  * Close network device
00492  *
00493  * @v netdev            Network device
00494  */
00495 static void icplus_close ( struct net_device *netdev ) {
00496         struct icplus_nic *icp = netdev->priv;
00497         unsigned int i;
00498 
00499         /* Perform global reset */
00500         icplus_reset ( icp );
00501 
00502         /* Destroy receive descriptor ring */
00503         icplus_destroy_ring ( icp, &icp->rx );
00504 
00505         /* Destroy transmit descriptor ring */
00506         icplus_destroy_ring ( icp, &icp->tx );
00507 
00508         /* Discard any unused receive buffers */
00509         for ( i = 0 ; i < ICP_NUM_DESC ; i++ ) {
00510                 if ( icp->rx_iobuf[i] )
00511                         free_iob ( icp->rx_iobuf[i] );
00512                 icp->rx_iobuf[i] = NULL;
00513         }
00514 }
00515 
00516 /**
00517  * Transmit packet
00518  *
00519  * @v netdev            Network device
00520  * @v iobuf             I/O buffer
00521  * @ret rc              Return status code
00522  */
00523 static int icplus_transmit ( struct net_device *netdev,
00524                              struct io_buffer *iobuf ) {
00525         struct icplus_nic *icp = netdev->priv;
00526         struct icplus_descriptor *desc;
00527         unsigned int tx_idx;
00528         physaddr_t address;
00529 
00530         /* Check if ring is full */
00531         if ( ( icp->tx.prod - icp->tx.cons ) >= ICP_NUM_DESC ) {
00532                 DBGC ( icp, "ICP %p out of transmit descriptors\n", icp );
00533                 return -ENOBUFS;
00534         }
00535 
00536         /* Find TX descriptor entry to use */
00537         tx_idx = ( icp->tx.prod++ % ICP_NUM_DESC );
00538         desc = &icp->tx.entry[tx_idx];
00539 
00540         /* Fill in TX descriptor */
00541         address = virt_to_bus ( iobuf->data );
00542         desc->data.address = cpu_to_le64 ( address );
00543         desc->data.len = cpu_to_le16 ( iob_len ( iobuf ) );
00544         wmb();
00545         desc->control = ICP_TX_SOLE_FRAG;
00546         wmb();
00547 
00548         /* Ring doorbell */
00549         writew ( ICP_DMACTRL_TXPOLLNOW, icp->regs + ICP_DMACTRL );
00550 
00551         DBGC2 ( icp, "ICP %p TX %d is [%llx,%llx)\n", icp, tx_idx,
00552                 ( ( unsigned long long ) address ),
00553                 ( ( unsigned long long ) address + iob_len ( iobuf ) ) );
00554         DBGC2_HDA ( icp, virt_to_phys ( desc ), desc, sizeof ( *desc ) );
00555         return 0;
00556 }
00557 
00558 /**
00559  * Poll for completed packets
00560  *
00561  * @v netdev            Network device
00562  */
00563 static void icplus_poll_tx ( struct net_device *netdev ) {
00564         struct icplus_nic *icp = netdev->priv;
00565         struct icplus_descriptor *desc;
00566         unsigned int tx_idx;
00567 
00568         /* Check for completed packets */
00569         while ( icp->tx.cons != icp->tx.prod ) {
00570 
00571                 /* Get next transmit descriptor */
00572                 tx_idx = ( icp->tx.cons % ICP_NUM_DESC );
00573                 desc = &icp->tx.entry[tx_idx];
00574 
00575                 /* Stop if descriptor is still in use */
00576                 if ( ! ( desc->control & ICP_DONE ) )
00577                         return;
00578 
00579                 /* Complete TX descriptor */
00580                 DBGC2 ( icp, "ICP %p TX %d complete\n", icp, tx_idx );
00581                 netdev_tx_complete_next ( netdev );
00582                 icp->tx.cons++;
00583         }
00584 }
00585 
00586 /**
00587  * Poll for received packets
00588  *
00589  * @v netdev            Network device
00590  */
00591 static void icplus_poll_rx ( struct net_device *netdev ) {
00592         struct icplus_nic *icp = netdev->priv;
00593         struct icplus_descriptor *desc;
00594         struct io_buffer *iobuf;
00595         unsigned int rx_idx;
00596         size_t len;
00597 
00598         /* Check for received packets */
00599         while ( icp->rx.cons != icp->rx.prod ) {
00600 
00601                 /* Get next transmit descriptor */
00602                 rx_idx = ( icp->rx.cons % ICP_NUM_DESC );
00603                 desc = &icp->rx.entry[rx_idx];
00604 
00605                 /* Stop if descriptor is still in use */
00606                 if ( ! ( desc->control & ICP_DONE ) )
00607                         return;
00608 
00609                 /* Populate I/O buffer */
00610                 iobuf = icp->rx_iobuf[rx_idx];
00611                 icp->rx_iobuf[rx_idx] = NULL;
00612                 len = le16_to_cpu ( desc->len );
00613                 iob_put ( iobuf, len );
00614 
00615                 /* Hand off to network stack */
00616                 if ( desc->flags & ( ICP_RX_ERR_OVERRUN | ICP_RX_ERR_RUNT |
00617                                      ICP_RX_ERR_ALIGN | ICP_RX_ERR_FCS |
00618                                      ICP_RX_ERR_OVERSIZED | ICP_RX_ERR_LEN ) ) {
00619                         DBGC ( icp, "ICP %p RX %d error (length %zd, "
00620                                "flags %02x)\n", icp, rx_idx, len, desc->flags );
00621                         netdev_rx_err ( netdev, iobuf, -EIO );
00622                 } else {
00623                         DBGC2 ( icp, "ICP %p RX %d complete (length "
00624                                 "%zd)\n", icp, rx_idx, len );
00625                         netdev_rx ( netdev, iobuf );
00626                 }
00627                 icp->rx.cons++;
00628         }
00629 }
00630 
00631 /**
00632  * Poll for completed and received packets
00633  *
00634  * @v netdev            Network device
00635  */
00636 static void icplus_poll ( struct net_device *netdev ) {
00637         struct icplus_nic *icp = netdev->priv;
00638         uint16_t intstatus;
00639         uint32_t txstatus;
00640 
00641         /* Check for interrupts */
00642         intstatus = readw ( icp->regs + ICP_INTSTATUS );
00643 
00644         /* Poll for TX completions, if applicable */
00645         if ( intstatus & ICP_INTSTATUS_TXCOMPLETE ) {
00646                 txstatus = readl ( icp->regs + ICP_TXSTATUS );
00647                 if ( txstatus & ICP_TXSTATUS_ERROR )
00648                         DBGC ( icp, "ICP %p TX error: %08x\n", icp, txstatus );
00649                 icplus_poll_tx ( netdev );
00650         }
00651 
00652         /* Poll for RX completions, if applicable */
00653         if ( intstatus & ICP_INTSTATUS_RXDMACOMPLETE ) {
00654                 writew ( ICP_INTSTATUS_RXDMACOMPLETE, icp->regs + ICP_INTSTATUS );
00655                 icplus_poll_rx ( netdev );
00656         }
00657 
00658         /* Check link state, if applicable */
00659         if ( intstatus & ICP_INTSTATUS_LINKEVENT ) {
00660                 writew ( ICP_INTSTATUS_LINKEVENT, icp->regs + ICP_INTSTATUS );
00661                 icplus_check_link ( netdev );
00662         }
00663 
00664         /* Refill receive ring */
00665         icplus_refill_rx ( icp );
00666 }
00667 
00668 /**
00669  * Enable or disable interrupts
00670  *
00671  * @v netdev            Network device
00672  * @v enable            Interrupts should be enabled
00673  */
00674 static void icplus_irq ( struct net_device *netdev, int enable ) {
00675         struct icplus_nic *icp = netdev->priv;
00676 
00677         DBGC ( icp, "ICPLUS %p does not yet support interrupts\n", icp );
00678         ( void ) enable;
00679 }
00680 
00681 /** IC+ network device operations */
00682 static struct net_device_operations icplus_operations = {
00683         .open           = icplus_open,
00684         .close          = icplus_close,
00685         .transmit       = icplus_transmit,
00686         .poll           = icplus_poll,
00687         .irq            = icplus_irq,
00688 };
00689 
00690 /******************************************************************************
00691  *
00692  * PCI interface
00693  *
00694  ******************************************************************************
00695  */
00696 
00697 /**
00698  * Probe PCI device
00699  *
00700  * @v pci               PCI device
00701  * @ret rc              Return status code
00702  */
00703 static int icplus_probe ( struct pci_device *pci ) {
00704         struct net_device *netdev;
00705         struct icplus_nic *icp;
00706         int rc;
00707 
00708         /* Allocate and initialise net device */
00709         netdev = alloc_etherdev ( sizeof ( *icp ) );
00710         if ( ! netdev ) {
00711                 rc = -ENOMEM;
00712                 goto err_alloc;
00713         }
00714         netdev_init ( netdev, &icplus_operations );
00715         icp = netdev->priv;
00716         pci_set_drvdata ( pci, netdev );
00717         netdev->dev = &pci->dev;
00718         memset ( icp, 0, sizeof ( *icp ) );
00719         icp->miibit.basher.op = &icplus_basher_ops;
00720         init_mii_bit_basher ( &icp->miibit );
00721         mii_init ( &icp->mii, &icp->miibit.mdio, 0 );
00722         icp->tx.listptr = ICP_TFDLISTPTR;
00723         icp->rx.listptr = ICP_RFDLISTPTR;
00724 
00725         /* Fix up PCI device */
00726         adjust_pci_device ( pci );
00727 
00728         /* Map registers */
00729         icp->regs = ioremap ( pci->membase, ICP_BAR_SIZE );
00730         if ( ! icp->regs ) {
00731                 rc = -ENODEV;
00732                 goto err_ioremap;
00733         }
00734 
00735         /* Reset the NIC */
00736         if ( ( rc = icplus_reset ( icp ) ) != 0 )
00737                 goto err_reset;
00738 
00739         /* Initialise EEPROM */
00740         icplus_init_eeprom ( icp );
00741 
00742         /* Read EEPROM MAC address */
00743         if ( ( rc = nvs_read ( &icp->eeprom, ICP_EEPROM_MAC,
00744                                netdev->hw_addr, ETH_ALEN ) ) != 0 ) {
00745                 DBGC ( icp, "ICPLUS %p could not read EEPROM MAC address: %s\n",
00746                        icp, strerror ( rc ) );
00747                 goto err_eeprom;
00748         }
00749 
00750         /* Configure PHY */
00751         if ( ( rc = icplus_init_phy ( icp ) ) != 0 )
00752                 goto err_phy;
00753 
00754         /* Register network device */
00755         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00756                 goto err_register_netdev;
00757 
00758         /* Set initial link state */
00759         icplus_check_link ( netdev );
00760 
00761         return 0;
00762 
00763         unregister_netdev ( netdev );
00764  err_register_netdev:
00765  err_phy:
00766  err_eeprom:
00767         icplus_reset ( icp );
00768  err_reset:
00769         iounmap ( icp->regs );
00770  err_ioremap:
00771         netdev_nullify ( netdev );
00772         netdev_put ( netdev );
00773  err_alloc:
00774         return rc;
00775 }
00776 
00777 /**
00778  * Remove PCI device
00779  *
00780  * @v pci               PCI device
00781  */
00782 static void icplus_remove ( struct pci_device *pci ) {
00783         struct net_device *netdev = pci_get_drvdata ( pci );
00784         struct icplus_nic *icp = netdev->priv;
00785 
00786         /* Unregister network device */
00787         unregister_netdev ( netdev );
00788 
00789         /* Reset card */
00790         icplus_reset ( icp );
00791 
00792         /* Free network device */
00793         iounmap ( icp->regs );
00794         netdev_nullify ( netdev );
00795         netdev_put ( netdev );
00796 }
00797 
00798 /** IC+ PCI device IDs */
00799 static struct pci_device_id icplus_nics[] = {
00800         PCI_ROM ( 0x13f0, 0x1023, "ip1000a",    "IP1000A", 0 ),
00801 };
00802 
00803 /** IC+ PCI driver */
00804 struct pci_driver icplus_driver __pci_driver = {
00805         .ids = icplus_nics,
00806         .id_count = ( sizeof ( icplus_nics ) / sizeof ( icplus_nics[0] ) ),
00807         .probe = icplus_probe,
00808         .remove = icplus_remove,
00809 };