iPXE
exanic.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2017 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 <strings.h>
00029 #include <unistd.h>
00030 #include <errno.h>
00031 #include <byteswap.h>
00032 #include <ipxe/netdevice.h>
00033 #include <ipxe/ethernet.h>
00034 #include <ipxe/if_ether.h>
00035 #include <ipxe/iobuf.h>
00036 #include <ipxe/malloc.h>
00037 #include <ipxe/umalloc.h>
00038 #include <ipxe/pci.h>
00039 #include "exanic.h"
00040 
00041 /** @file
00042  *
00043  * Exablaze ExaNIC driver
00044  *
00045  */
00046 
00047 /* Disambiguate the various error causes */
00048 #define EIO_ABORTED __einfo_error ( EINFO_EIO_ABORTED )
00049 #define EINFO_EIO_ABORTED \
00050         __einfo_uniqify ( EINFO_EIO, 0x01, "Frame aborted" )
00051 #define EIO_CORRUPT __einfo_error ( EINFO_EIO_CORRUPT )
00052 #define EINFO_EIO_CORRUPT \
00053         __einfo_uniqify ( EINFO_EIO, 0x02, "CRC incorrect" )
00054 #define EIO_HWOVFL __einfo_error ( EINFO_EIO_HWOVFL )
00055 #define EINFO_EIO_HWOVFL \
00056         __einfo_uniqify ( EINFO_EIO, 0x03, "Hardware overflow" )
00057 #define EIO_STATUS( status ) \
00058         EUNIQ ( EINFO_EIO, ( (status) & EXANIC_STATUS_ERROR_MASK ), \
00059                 EIO_ABORTED, EIO_CORRUPT, EIO_HWOVFL )
00060 
00061 /**
00062  * Write DMA base address register
00063  *
00064  * @v addr              DMA base address
00065  * @v reg               Register
00066  */
00067 static void exanic_write_base ( physaddr_t addr, void *reg ) {
00068         uint32_t lo;
00069         uint32_t hi;
00070 
00071         /* Write high and low registers, setting flags as appropriate */
00072         lo = addr;
00073         if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) {
00074                 /* 64-bit build; may be a 32-bit or 64-bit address */
00075                 hi = ( ( ( uint64_t ) addr ) >> 32 );
00076                 if ( ! hi )
00077                         lo |= EXANIC_DMA_32_BIT;
00078         } else {
00079                 /* 32-bit build; always a 32-bit address */
00080                 hi = 0;
00081                 lo |= EXANIC_DMA_32_BIT;
00082         }
00083         writel ( hi, ( reg + 0 ) );
00084         writel ( lo, ( reg + 4 ) );
00085 }
00086 
00087 /**
00088  * Clear DMA base address register
00089  *
00090  * @v reg               Register
00091  */
00092 static inline void exanic_clear_base ( void *reg ) {
00093 
00094         /* Clear both high and low registers */
00095         writel ( 0, ( reg + 0 ) );
00096         writel ( 0, ( reg + 4 ) );
00097 }
00098 
00099 /******************************************************************************
00100  *
00101  * Device reset
00102  *
00103  ******************************************************************************
00104  */
00105 
00106 /**
00107  * Reset hardware
00108  *
00109  * @v exanic            ExaNIC device
00110  */
00111 static void exanic_reset ( struct exanic *exanic ) {
00112         void *port_regs;
00113         unsigned int i;
00114 
00115         /* Disable all possible ports */
00116         for ( i = 0 ; i < EXANIC_MAX_PORTS ; i++ ) {
00117                 port_regs = ( exanic->regs + EXANIC_PORT_REGS ( i ) );
00118                 writel ( 0, ( port_regs + EXANIC_PORT_ENABLE ) );
00119                 writel ( 0, ( port_regs + EXANIC_PORT_IRQ ) );
00120                 exanic_clear_base ( port_regs + EXANIC_PORT_RX_BASE );
00121         }
00122 
00123         /* Disable transmit feedback */
00124         exanic_clear_base ( exanic->regs + EXANIC_TXF_BASE );
00125 }
00126 
00127 /******************************************************************************
00128  *
00129  * MAC address
00130  *
00131  ******************************************************************************
00132  */
00133 
00134 /**
00135  * Read I2C line status
00136  *
00137  * @v basher            Bit-bashing interface
00138  * @v bit_id            Bit number
00139  * @ret zero            Input is a logic 0
00140  * @ret non-zero        Input is a logic 1
00141  */
00142 static int exanic_i2c_read_bit ( struct bit_basher *basher,
00143                                  unsigned int bit_id ) {
00144         struct exanic *exanic =
00145                 container_of ( basher, struct exanic, basher.basher );
00146         unsigned int shift;
00147         uint32_t i2c;
00148 
00149         /* Identify bit */
00150         assert ( bit_id == I2C_BIT_SDA );
00151         shift = exanic->i2cfg.getsda;
00152 
00153         /* Read I2C register */
00154         DBG_DISABLE ( DBGLVL_IO );
00155         i2c = readl ( exanic->regs + EXANIC_I2C );
00156         DBG_ENABLE ( DBGLVL_IO );
00157         return ( ( i2c >> shift ) & 1 );
00158 }
00159 
00160 /**
00161  * Write I2C line status
00162  *
00163  * @v basher            Bit-bashing interface
00164  * @v bit_id            Bit number
00165  * @v data              Value to write
00166  */
00167 static void exanic_i2c_write_bit ( struct bit_basher *basher,
00168                                    unsigned int bit_id, unsigned long data ) {
00169         struct exanic *exanic =
00170                 container_of ( basher, struct exanic, basher.basher );
00171         unsigned int shift;
00172         uint32_t mask;
00173         uint32_t i2c;
00174 
00175         /* Identify shift */
00176         assert ( ( bit_id == I2C_BIT_SCL ) || ( bit_id == I2C_BIT_SDA ) );
00177         shift = ( ( bit_id == I2C_BIT_SCL ) ?
00178                   exanic->i2cfg.setscl : exanic->i2cfg.setsda );
00179         mask = ( 1UL << shift );
00180 
00181         /* Modify I2C register */
00182         DBG_DISABLE ( DBGLVL_IO );
00183         i2c = readl ( exanic->regs + EXANIC_I2C );
00184         i2c &= ~mask;
00185         if ( ! data )
00186                 i2c |= mask;
00187         writel ( i2c, ( exanic->regs + EXANIC_I2C ) );
00188         DBG_ENABLE ( DBGLVL_IO );
00189 }
00190 
00191 /** I2C bit-bashing interface operations */
00192 static struct bit_basher_operations exanic_i2c_basher_ops = {
00193         .read = exanic_i2c_read_bit,
00194         .write = exanic_i2c_write_bit,
00195 };
00196 
00197 /** Possible I2C bus configurations */
00198 static struct exanic_i2c_config exanic_i2cfgs[] = {
00199         /* X2/X10 */
00200         { .setscl = 7, .setsda = 4, .getsda = 12 },
00201         /* X4 */
00202         { .setscl = 7, .setsda = 5, .getsda = 13 },
00203 };
00204 
00205 /**
00206  * Initialise EEPROM
00207  *
00208  * @v exanic            ExaNIC device
00209  * @v i2cfg             I2C bus configuration
00210  * @ret rc              Return status code
00211  */
00212 static int exanic_try_init_eeprom ( struct exanic *exanic,
00213                                     struct exanic_i2c_config *i2cfg ) {
00214         int rc;
00215 
00216         /* Configure I2C bus */
00217         memcpy ( &exanic->i2cfg, i2cfg, sizeof ( exanic->i2cfg ) );
00218 
00219         /* Initialise I2C bus */
00220         if ( ( rc = init_i2c_bit_basher ( &exanic->basher,
00221                                           &exanic_i2c_basher_ops ) ) != 0 ) {
00222                 DBGC2 ( exanic, "EXANIC %p found no I2C bus via %d/%d/%d\n",
00223                         exanic, exanic->i2cfg.setscl,
00224                         exanic->i2cfg.setsda, exanic->i2cfg.getsda );
00225                 return rc;
00226         }
00227 
00228         /* Check for EEPROM presence */
00229         init_i2c_eeprom ( &exanic->eeprom, EXANIC_EEPROM_ADDRESS );
00230         if ( ( rc = i2c_check_presence ( &exanic->basher.i2c,
00231                                          &exanic->eeprom ) ) != 0 ) {
00232                 DBGC2 ( exanic, "EXANIC %p found no EEPROM via %d/%d/%d\n",
00233                         exanic, exanic->i2cfg.setscl,
00234                         exanic->i2cfg.setsda, exanic->i2cfg.getsda );
00235                 return rc;
00236         }
00237 
00238         DBGC ( exanic, "EXANIC %p found EEPROM via %d/%d/%d\n",
00239                exanic, exanic->i2cfg.setscl,
00240                exanic->i2cfg.setsda, exanic->i2cfg.getsda );
00241         return 0;
00242 }
00243 
00244 /**
00245  * Initialise EEPROM
00246  *
00247  * @v exanic            ExaNIC device
00248  * @ret rc              Return status code
00249  */
00250 static int exanic_init_eeprom ( struct exanic *exanic ) {
00251         struct exanic_i2c_config *i2cfg;
00252         unsigned int i;
00253         int rc;
00254 
00255         /* Try all possible bus configurations */
00256         for ( i = 0 ; i < ( sizeof ( exanic_i2cfgs ) /
00257                             sizeof ( exanic_i2cfgs[0] ) ) ; i++ ) {
00258                 i2cfg = &exanic_i2cfgs[i];
00259                 if ( ( rc = exanic_try_init_eeprom ( exanic, i2cfg ) ) == 0 )
00260                         return 0;
00261         }
00262 
00263         DBGC ( exanic, "EXANIC %p found no EEPROM\n", exanic );
00264         return -ENODEV;
00265 }
00266 
00267 /**
00268  * Fetch base MAC address
00269  *
00270  * @v exanic            ExaNIC device
00271  * @ret rc              Return status code
00272  */
00273 static int exanic_fetch_mac ( struct exanic *exanic ) {
00274         struct i2c_interface *i2c = &exanic->basher.i2c;
00275         int rc;
00276 
00277         /* Initialise EEPROM */
00278         if ( ( rc = exanic_init_eeprom ( exanic ) ) != 0 )
00279                 return rc;
00280 
00281         /* Fetch base MAC address */
00282         if ( ( rc = i2c->read ( i2c, &exanic->eeprom, 0, exanic->mac,
00283                                 sizeof ( exanic->mac ) ) ) != 0 ) {
00284                 DBGC ( exanic, "EXANIC %p could not read MAC address: %s\n",
00285                        exanic, strerror ( rc ) );
00286                 return rc;
00287         }
00288 
00289         return 0;
00290 }
00291 
00292 /******************************************************************************
00293  *
00294  * Link state
00295  *
00296  ******************************************************************************
00297  */
00298 
00299 /**
00300  * Check link state
00301  *
00302  * @v netdev            Network device
00303  */
00304 static void exanic_check_link ( struct net_device *netdev ) {
00305         struct exanic_port *port = netdev->priv;
00306         uint32_t status;
00307         uint32_t speed;
00308 
00309         /* Report port status changes */
00310         status = readl ( port->regs + EXANIC_PORT_STATUS );
00311         speed = readl ( port->regs + EXANIC_PORT_SPEED );
00312         if ( status != port->status ) {
00313                 DBGC ( port, "EXANIC %s port status %#08x speed %dMbps\n",
00314                        netdev->name, status, speed );
00315                 if ( status & EXANIC_PORT_STATUS_LINK ) {
00316                         netdev_link_up ( netdev );
00317                 } else {
00318                         netdev_link_down ( netdev );
00319                 }
00320                 port->status = status;
00321         }
00322 }
00323 
00324 /**
00325  * Check link state periodically
00326  *
00327  * @v retry             Link state check timer
00328  * @v over              Failure indicator
00329  */
00330 static void exanic_expired ( struct retry_timer *timer, int over __unused ) {
00331         struct exanic_port *port =
00332                 container_of ( timer, struct exanic_port, timer );
00333         struct net_device *netdev = port->netdev;
00334         static const uint32_t speeds[] = {
00335                 100, 1000, 10000, 40000, 100000,
00336         };
00337         unsigned int index;
00338 
00339         /* Restart timer */
00340         start_timer_fixed ( timer, EXANIC_LINK_INTERVAL );
00341 
00342         /* Check link state */
00343         exanic_check_link ( netdev );
00344 
00345         /* Do nothing further if link is already up */
00346         if ( netdev_link_ok ( netdev ) )
00347                 return;
00348 
00349         /* Do nothing further unless we have a valid list of supported speeds */
00350         if ( ! port->speeds )
00351                 return;
00352 
00353         /* Autonegotiation is not supported; try manually selecting
00354          * the next supported link speed.
00355          */
00356         do {
00357                 if ( ! port->speed )
00358                         port->speed = ( 8 * sizeof ( port->speeds ) );
00359                 port->speed--;
00360         } while ( ! ( ( 1UL << port->speed ) & port->speeds ) );
00361         index = ( port->speed - ( ffs ( EXANIC_CAPS_SPEED_MASK ) - 1 ) );
00362         assert ( index < ( sizeof ( speeds ) / sizeof ( speeds[0] ) ) );
00363 
00364         /* Attempt the selected speed */
00365         DBGC ( netdev, "EXANIC %s attempting %dMbps\n",
00366                netdev->name, speeds[index] );
00367         writel ( speeds[index], ( port->regs + EXANIC_PORT_SPEED ) );
00368 }
00369 
00370 /******************************************************************************
00371  *
00372  * Network device interface
00373  *
00374  ******************************************************************************
00375  */
00376 
00377 /**
00378  * Open network device
00379  *
00380  * @v netdev            Network device
00381  * @ret rc              Return status code
00382  */
00383 static int exanic_open ( struct net_device *netdev ) {
00384         struct exanic_port *port = netdev->priv;
00385         struct exanic_tx_chunk *tx;
00386         unsigned int i;
00387 
00388         /* Reset transmit region contents */
00389         for ( i = 0 ; i < port->tx_count ; i++ ) {
00390                 tx = ( port->tx + ( i * sizeof ( *tx ) ) );
00391                 writew ( port->txf_slot, &tx->desc.txf_slot );
00392                 writeb ( EXANIC_TYPE_RAW, &tx->desc.type );
00393                 writeb ( 0, &tx->desc.flags );
00394                 writew ( 0, &tx->pad );
00395         }
00396 
00397         /* Reset receive region contents */
00398         memset_user ( port->rx, 0, 0xff, EXANIC_RX_LEN );
00399 
00400         /* Reset transmit feedback region */
00401         *(port->txf) = 0;
00402 
00403         /* Reset counters */
00404         port->tx_prod = 0;
00405         port->tx_cons = 0;
00406         port->rx_cons = 0;
00407 
00408         /* Map receive region */
00409         exanic_write_base ( phys_to_bus ( user_to_phys ( port->rx, 0 ) ),
00410                             ( port->regs + EXANIC_PORT_RX_BASE ) );
00411 
00412         /* Enable promiscuous mode */
00413         writel ( EXANIC_PORT_FLAGS_PROMISC,
00414                  ( port->regs + EXANIC_PORT_FLAGS ) );
00415 
00416         /* Reset to default speed and clear cached status */
00417         writel ( port->default_speed, ( port->regs + EXANIC_PORT_SPEED ) );
00418         port->speed = 0;
00419         port->status = 0;
00420 
00421         /* Enable port */
00422         wmb();
00423         writel ( EXANIC_PORT_ENABLE_ENABLED,
00424                  ( port->regs + EXANIC_PORT_ENABLE ) );
00425 
00426         /* Start link state timer */
00427         start_timer_fixed ( &port->timer, EXANIC_LINK_INTERVAL );
00428 
00429         return 0;
00430 }
00431 
00432 /**
00433  * Close network device
00434  *
00435  * @v netdev            Network device
00436  */
00437 static void exanic_close ( struct net_device *netdev ) {
00438         struct exanic_port *port = netdev->priv;
00439 
00440         /* Stop link state timer */
00441         stop_timer ( &port->timer );
00442 
00443         /* Disable port */
00444         writel ( 0, ( port->regs + EXANIC_PORT_ENABLE ) );
00445         wmb();
00446 
00447         /* Clear receive region */
00448         exanic_clear_base ( port->regs + EXANIC_PORT_RX_BASE );
00449 
00450         /* Discard any in-progress receive */
00451         if ( port->rx_iobuf ) {
00452                 netdev_rx_err ( netdev, port->rx_iobuf, -ECANCELED );
00453                 port->rx_iobuf = NULL;
00454         }
00455 }
00456 
00457 /**
00458  * Transmit packet
00459  *
00460  * @v netdev            Network device
00461  * @v iobuf             I/O buffer
00462  * @ret rc              Return status code
00463  */
00464 static int exanic_transmit ( struct net_device *netdev,
00465                              struct io_buffer *iobuf ) {
00466         struct exanic_port *port = netdev->priv;
00467         struct exanic_tx_chunk *tx;
00468         unsigned int tx_fill;
00469         unsigned int tx_index;
00470         size_t offset;
00471         size_t len;
00472         uint8_t *src;
00473         uint8_t *dst;
00474 
00475         /* Sanity check */
00476         len = iob_len ( iobuf );
00477         if ( len > sizeof ( tx->data ) ) {
00478                 DBGC ( port, "EXANIC %s transmit too large\n", netdev->name );
00479                 return -ENOTSUP;
00480         }
00481 
00482         /* Get next transmit descriptor */
00483         tx_fill = ( port->tx_prod - port->tx_cons );
00484         if ( tx_fill >= port->tx_count ) {
00485                 DBGC ( port, "EXANIC %s out of transmit descriptors\n",
00486                        netdev->name );
00487                 return -ENOBUFS;
00488         }
00489         tx_index = ( port->tx_prod & ( port->tx_count - 1 ) );
00490         offset = ( tx_index * sizeof ( *tx ) );
00491         tx = ( port->tx + offset );
00492         DBGC2 ( port, "EXANIC %s TX %04x at [%05zx,%05zx)\n",
00493                 netdev->name, port->tx_prod, ( port->tx_offset + offset ),
00494                 ( port->tx_offset + offset +
00495                   offsetof ( typeof ( *tx ), data ) + len ) );
00496         port->tx_prod++;
00497 
00498         /* Populate transmit descriptor */
00499         writew ( port->tx_prod, &tx->desc.txf_id );
00500         writew ( ( sizeof ( tx->pad ) + len ), &tx->desc.len );
00501 
00502         /* Copy data to transmit region.  There is no DMA on the
00503          * transmit data path.
00504          */
00505         src = iobuf->data;
00506         dst = tx->data;
00507         while ( len-- )
00508                 writeb ( *(src++), dst++ );
00509 
00510         /* Send transmit command */
00511         wmb();
00512         writel ( ( port->tx_offset + offset ),
00513                  ( port->regs + EXANIC_PORT_TX_COMMAND ) );
00514 
00515         return 0;
00516 }
00517 
00518 /**
00519  * Poll for completed packets
00520  *
00521  * @v netdev            Network device
00522  */
00523 static void exanic_poll_tx ( struct net_device *netdev ) {
00524         struct exanic_port *port = netdev->priv;
00525 
00526         /* Report any completed packets */
00527         while ( port->tx_cons != *(port->txf) ) {
00528                 DBGC2 ( port, "EXANIC %s TX %04x complete\n",
00529                         netdev->name, port->tx_cons );
00530                 netdev_tx_complete_next ( netdev );
00531                 port->tx_cons++;
00532         }
00533 }
00534 
00535 /**
00536  * Poll for received packets
00537  *
00538  * @v netdev            Network device
00539  */
00540 static void exanic_poll_rx ( struct net_device *netdev ) {
00541         struct exanic_port *port = netdev->priv;
00542         struct exanic_rx_chunk *rx;
00543         struct exanic_rx_descriptor desc;
00544         uint8_t current;
00545         uint8_t previous;
00546         size_t offset;
00547         size_t len;
00548 
00549         for ( ; ; port->rx_cons++ ) {
00550 
00551                 /* Fetch descriptor */
00552                 offset = ( ( port->rx_cons * sizeof ( *rx ) ) % EXANIC_RX_LEN );
00553                 copy_from_user ( &desc, port->rx,
00554                                  ( offset + offsetof ( typeof ( *rx ), desc ) ),
00555                                  sizeof ( desc ) );
00556 
00557                 /* Calculate generation */
00558                 current = ( port->rx_cons / ( EXANIC_RX_LEN / sizeof ( *rx ) ));
00559                 previous = ( current - 1 );
00560 
00561                 /* Do nothing if no chunk is ready */
00562                 if ( desc.generation == previous )
00563                         break;
00564 
00565                 /* Allocate I/O buffer if needed */
00566                 if ( ! port->rx_iobuf ) {
00567                         port->rx_iobuf = alloc_iob ( EXANIC_MAX_RX_LEN );
00568                         if ( ! port->rx_iobuf ) {
00569                                 /* Wait for next poll */
00570                                 break;
00571                         }
00572                         port->rx_rc = 0;
00573                 }
00574 
00575                 /* Calculate chunk length */
00576                 len = ( desc.len ? desc.len : sizeof ( rx->data ) );
00577 
00578                 /* Append data to I/O buffer */
00579                 if ( len <= iob_tailroom ( port->rx_iobuf ) ) {
00580                         copy_from_user ( iob_put ( port->rx_iobuf, len ),
00581                                          port->rx,
00582                                          ( offset + offsetof ( typeof ( *rx ),
00583                                                                data ) ), len );
00584                 } else {
00585                         DBGC ( port, "EXANIC %s RX too large\n",
00586                                netdev->name );
00587                         port->rx_rc = -ERANGE;
00588                 }
00589 
00590                 /* Check for overrun */
00591                 rmb();
00592                 copy_from_user ( &desc.generation, port->rx,
00593                                  ( offset + offsetof ( typeof ( *rx ),
00594                                                        desc.generation ) ),
00595                                  sizeof ( desc.generation ) );
00596                 if ( desc.generation != current ) {
00597                         DBGC ( port, "EXANIC %s RX overrun\n", netdev->name );
00598                         port->rx_rc = -ENOBUFS;
00599                         continue;
00600                 }
00601 
00602                 /* Wait for end of packet */
00603                 if ( ! desc.len )
00604                         continue;
00605 
00606                 /* Check for receive errors */
00607                 if ( desc.status & EXANIC_STATUS_ERROR_MASK ) {
00608                         port->rx_rc = -EIO_STATUS ( desc.status );
00609                         DBGC ( port, "EXANIC %s RX %04x error: %s\n",
00610                                netdev->name, port->rx_cons,
00611                                strerror ( port->rx_rc ) );
00612                 } else {
00613                         DBGC2 ( port, "EXANIC %s RX %04x\n",
00614                                 netdev->name, port->rx_cons );
00615                 }
00616 
00617                 /* Hand off to network stack */
00618                 if ( port->rx_rc ) {
00619                         netdev_rx_err ( netdev, port->rx_iobuf, port->rx_rc );
00620                 } else {
00621                         iob_unput ( port->rx_iobuf, 4 /* strip CRC */ );
00622                         netdev_rx ( netdev, port->rx_iobuf );
00623                 }
00624                 port->rx_iobuf = NULL;
00625         }
00626 }
00627 
00628 /**
00629  * Poll for completed and received packets
00630  *
00631  * @v netdev            Network device
00632  */
00633 static void exanic_poll ( struct net_device *netdev ) {
00634 
00635         /* Poll for completed packets */
00636         exanic_poll_tx ( netdev );
00637 
00638         /* Poll for received packets */
00639         exanic_poll_rx ( netdev );
00640 }
00641 
00642 /** ExaNIC network device operations */
00643 static struct net_device_operations exanic_operations = {
00644         .open           = exanic_open,
00645         .close          = exanic_close,
00646         .transmit       = exanic_transmit,
00647         .poll           = exanic_poll,
00648 };
00649 
00650 /******************************************************************************
00651  *
00652  * PCI interface
00653  *
00654  ******************************************************************************
00655  */
00656 
00657 /**
00658  * Probe port
00659  *
00660  * @v exanic            ExaNIC device
00661  * @v dev               Parent device
00662  * @v index             Port number
00663  * @ret rc              Return status code
00664  */
00665 static int exanic_probe_port ( struct exanic *exanic, struct device *dev,
00666                                unsigned int index ) {
00667         struct net_device *netdev;
00668         struct exanic_port *port;
00669         void *port_regs;
00670         uint32_t status;
00671         size_t tx_len;
00672         int rc;
00673 
00674         /* Do nothing if port is not physically present */
00675         port_regs = ( exanic->regs + EXANIC_PORT_REGS ( index ) );
00676         status = readl ( port_regs + EXANIC_PORT_STATUS );
00677         tx_len = readl ( port_regs + EXANIC_PORT_TX_LEN );
00678         if ( ( status & EXANIC_PORT_STATUS_ABSENT ) || ( tx_len == 0 ) ) {
00679                 rc = 0;
00680                 goto absent;
00681         }
00682 
00683         /* Allocate network device */
00684         netdev = alloc_etherdev ( sizeof ( *port ) );
00685         if ( ! netdev ) {
00686                 rc = -ENOMEM;
00687                 goto err_alloc_netdev;
00688         }
00689         netdev_init ( netdev, &exanic_operations );
00690         netdev->dev = dev;
00691         port = netdev->priv;
00692         memset ( port, 0, sizeof ( *port ) );
00693         exanic->port[index] = port;
00694         port->netdev = netdev;
00695         port->regs = port_regs;
00696         timer_init ( &port->timer, exanic_expired, &netdev->refcnt );
00697 
00698         /* Identify transmit region */
00699         port->tx_offset = readl ( port->regs + EXANIC_PORT_TX_OFFSET );
00700         if ( tx_len > EXANIC_MAX_TX_LEN )
00701                 tx_len = EXANIC_MAX_TX_LEN;
00702         assert ( ! ( tx_len & ( tx_len - 1 ) ) );
00703         port->tx = ( exanic->tx + port->tx_offset );
00704         port->tx_count = ( tx_len / sizeof ( struct exanic_tx_chunk ) );
00705 
00706         /* Identify transmit feedback region */
00707         port->txf_slot = EXANIC_TXF_SLOT ( index );
00708         port->txf = ( exanic->txf +
00709                       ( port->txf_slot * sizeof ( *(port->txf) ) ) );
00710 
00711         /* Allocate receive region (via umalloc()) */
00712         port->rx = umalloc ( EXANIC_RX_LEN );
00713         if ( ! port->rx ) {
00714                 rc = -ENOMEM;
00715                 goto err_alloc_rx;
00716         }
00717 
00718         /* Set MAC address */
00719         memcpy ( netdev->hw_addr, exanic->mac, ETH_ALEN );
00720         netdev->hw_addr[ ETH_ALEN - 1 ] += index;
00721 
00722         /* Record default link speed and supported speeds */
00723         port->default_speed = readl ( port->regs + EXANIC_PORT_SPEED );
00724         port->speeds = ( exanic->caps & EXANIC_CAPS_SPEED_MASK );
00725 
00726         /* Register network device */
00727         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00728                 goto err_register_netdev;
00729         DBGC ( port, "EXANIC %s port %d TX [%#05zx,%#05zx) TXF %#02x RX "
00730                "[%#lx,%#lx)\n", netdev->name, index, port->tx_offset,
00731                ( port->tx_offset + tx_len ), port->txf_slot,
00732                user_to_phys ( port->rx, 0 ),
00733                user_to_phys ( port->rx, EXANIC_RX_LEN ) );
00734 
00735         /* Set initial link state */
00736         exanic_check_link ( netdev );
00737 
00738         return 0;
00739 
00740         unregister_netdev ( netdev );
00741  err_register_netdev:
00742         ufree ( port->rx );
00743  err_alloc_rx:
00744         netdev_nullify ( netdev );
00745         netdev_put ( netdev );
00746  err_alloc_netdev:
00747  absent:
00748         return rc;
00749 }
00750 
00751 /**
00752  * Probe port
00753  *
00754  * @v exanic            ExaNIC device
00755  * @v index             Port number
00756  */
00757 static void exanic_remove_port ( struct exanic *exanic, unsigned int index ) {
00758         struct exanic_port *port;
00759 
00760         /* Do nothing if port is not physically present */
00761         port = exanic->port[index];
00762         if ( ! port )
00763                 return;
00764 
00765         /* Unregister network device */
00766         unregister_netdev ( port->netdev );
00767 
00768         /* Free receive region */
00769         ufree ( port->rx );
00770 
00771         /* Free network device */
00772         netdev_nullify ( port->netdev );
00773         netdev_put ( port->netdev );
00774 }
00775 
00776 /**
00777  * Probe PCI device
00778  *
00779  * @v pci               PCI device
00780  * @ret rc              Return status code
00781  */
00782 static int exanic_probe ( struct pci_device *pci ) {
00783         struct exanic *exanic;
00784         unsigned long regs_bar_start;
00785         unsigned long tx_bar_start;
00786         size_t tx_bar_len;
00787         int i;
00788         int rc;
00789 
00790         /* Allocate and initialise structure */
00791         exanic = zalloc ( sizeof ( *exanic ) );
00792         if ( ! exanic ) {
00793                 rc = -ENOMEM;
00794                 goto err_alloc;
00795         }
00796         pci_set_drvdata ( pci, exanic );
00797 
00798         /* Fix up PCI device */
00799         adjust_pci_device ( pci );
00800 
00801         /* Map registers */
00802         regs_bar_start = pci_bar_start ( pci, EXANIC_REGS_BAR );
00803         exanic->regs = ioremap ( regs_bar_start, EXANIC_REGS_LEN );
00804         if ( ! exanic->regs ) {
00805                 rc = -ENODEV;
00806                 goto err_ioremap_regs;
00807         }
00808 
00809         /* Reset device */
00810         exanic_reset ( exanic );
00811 
00812         /* Read capabilities */
00813         exanic->caps = readl ( exanic->regs + EXANIC_CAPS );
00814 
00815         /* Power up PHYs */
00816         writel ( EXANIC_POWER_ON, ( exanic->regs + EXANIC_POWER ) );
00817 
00818         /* Fetch base MAC address */
00819         if ( ( rc = exanic_fetch_mac ( exanic ) ) != 0 )
00820                 goto err_fetch_mac;
00821         DBGC ( exanic, "EXANIC %p capabilities %#08x base MAC %s\n",
00822                exanic, exanic->caps, eth_ntoa ( exanic->mac ) );
00823 
00824         /* Map transmit region */
00825         tx_bar_start = pci_bar_start ( pci, EXANIC_TX_BAR );
00826         tx_bar_len = pci_bar_size ( pci, EXANIC_TX_BAR );
00827         exanic->tx = ioremap ( tx_bar_start, tx_bar_len );
00828         if ( ! exanic->tx ) {
00829                 rc = -ENODEV;
00830                 goto err_ioremap_tx;
00831         }
00832 
00833         /* Allocate transmit feedback region (shared between all ports) */
00834         exanic->txf = malloc_dma ( EXANIC_TXF_LEN, EXANIC_ALIGN );
00835         if ( ! exanic->txf ) {
00836                 rc = -ENOMEM;
00837                 goto err_alloc_txf;
00838         }
00839         memset ( exanic->txf, 0, EXANIC_TXF_LEN );
00840         exanic_write_base ( virt_to_bus ( exanic->txf ),
00841                             ( exanic->regs + EXANIC_TXF_BASE ) );
00842 
00843         /* Allocate and initialise per-port network devices */
00844         for ( i = 0 ; i < EXANIC_MAX_PORTS ; i++ ) {
00845                 if ( ( rc = exanic_probe_port ( exanic, &pci->dev, i ) ) != 0 )
00846                         goto err_probe_port;
00847         }
00848 
00849         return 0;
00850 
00851         i = EXANIC_MAX_PORTS;
00852  err_probe_port:
00853         for ( i-- ; i >= 0 ; i-- )
00854                 exanic_remove_port ( exanic, i );
00855         exanic_reset ( exanic );
00856         free_dma ( exanic->txf, EXANIC_TXF_LEN );
00857  err_alloc_txf:
00858         iounmap ( exanic->tx );
00859  err_ioremap_tx:
00860         iounmap ( exanic->regs );
00861  err_fetch_mac:
00862  err_ioremap_regs:
00863         free ( exanic );
00864  err_alloc:
00865         return rc;
00866 }
00867 
00868 /**
00869  * Remove PCI device
00870  *
00871  * @v pci               PCI device
00872  */
00873 static void exanic_remove ( struct pci_device *pci ) {
00874         struct exanic *exanic = pci_get_drvdata ( pci );
00875         unsigned int i;
00876 
00877         /* Remove all ports */
00878         for ( i = 0 ; i < EXANIC_MAX_PORTS ; i++ )
00879                 exanic_remove_port ( exanic, i );
00880 
00881         /* Reset device */
00882         exanic_reset ( exanic );
00883 
00884         /* Free transmit feedback region */
00885         free_dma ( exanic->txf, EXANIC_TXF_LEN );
00886 
00887         /* Unmap transmit region */
00888         iounmap ( exanic->tx );
00889 
00890         /* Unmap registers */
00891         iounmap ( exanic->regs );
00892 
00893         /* Free device */
00894         free ( exanic );
00895 }
00896 
00897 /** ExaNIC PCI device IDs */
00898 static struct pci_device_id exanic_ids[] = {
00899         PCI_ROM ( 0x10ee, 0x2b00, "exanic-old", "ExaNIC (old)", 0 ),
00900         PCI_ROM ( 0x1ce4, 0x0001, "exanic-x4", "ExaNIC X4", 0 ),
00901         PCI_ROM ( 0x1ce4, 0x0002, "exanic-x2", "ExaNIC X2", 0 ),
00902         PCI_ROM ( 0x1ce4, 0x0003, "exanic-x10", "ExaNIC X10", 0 ),
00903         PCI_ROM ( 0x1ce4, 0x0004, "exanic-x10gm", "ExaNIC X10 GM", 0 ),
00904         PCI_ROM ( 0x1ce4, 0x0005, "exanic-x40", "ExaNIC X40", 0 ),
00905         PCI_ROM ( 0x1ce4, 0x0006, "exanic-x10hpt", "ExaNIC X10 HPT", 0 ),
00906         PCI_ROM ( 0x1ce4, 0x0007, "exanic-x40g", "ExaNIC X40", 0 ),
00907 };
00908 
00909 /** ExaNIC PCI driver */
00910 struct pci_driver exanic_driver __pci_driver = {
00911         .ids = exanic_ids,
00912         .id_count = ( sizeof ( exanic_ids ) / sizeof ( exanic_ids[0] ) ),
00913         .probe = exanic_probe,
00914         .remove = exanic_remove,
00915 };