Annotation of qemu/roms/ipxe/src/drivers/net/myri10ge.c, revision 1.1

1.1     ! root        1: /************************************************* -*- linux-c -*-
        !             2:  * Myricom 10Gb Network Interface Card Software
        !             3:  * Copyright 2009, Myricom, Inc.
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or
        !             6:  * modify it under the terms of the GNU General Public License,
        !             7:  * version 2, as published by the Free Software Foundation.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful,
        !            10:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            12:  * GNU General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with this program; if not, write to the Free Software
        !            16:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !            17:  ****************************************************************/
        !            18: 
        !            19: FILE_LICENCE ( GPL2_ONLY );
        !            20: 
        !            21: /*
        !            22:  * Author: Glenn Brown <[email protected]>
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  * General Theory of Operation
        !            27:  *
        !            28:  * This is a minimal Myricom 10 gigabit Ethernet driver for network
        !            29:  * boot.
        !            30:  *
        !            31:  * Initialization
        !            32:  *
        !            33:  * myri10ge_pci_probe() is called by iPXE during initialization.
        !            34:  * Minimal NIC initialization is performed to minimize resources
        !            35:  * consumed when the driver is resident but unused.
        !            36:  *
        !            37:  * Network Boot
        !            38:  *
        !            39:  * myri10ge_net_open() is called by iPXE before attempting to network
        !            40:  * boot from the card.  Packet buffers are allocated and the NIC
        !            41:  * interface is initialized.
        !            42:  *
        !            43:  * Transmit
        !            44:  *
        !            45:  * myri10ge_net_transmit() enqueues frames for transmission by writing
        !            46:  * discriptors to the NIC's tx ring.  For simplicity and to avoid
        !            47:  * copies, we always have the NIC DMA up the packet.  The sent I/O
        !            48:  * buffer is released once the NIC signals myri10ge_interrupt_handler()
        !            49:  * that the send has completed.
        !            50:  *
        !            51:  * Receive
        !            52:  *
        !            53:  * Receives are posted to the NIC's receive ring.  The NIC fills a
        !            54:  * DMAable receive_completion ring with completion notifications.
        !            55:  * myri10ge_net_poll() polls for these receive notifications, posts
        !            56:  * replacement receive buffers to the NIC, and passes received frames
        !            57:  * to netdev_rx().
        !            58:  *
        !            59:  * NonVolatile Storage
        !            60:  *
        !            61:  * This driver supports NonVolatile Storage (nvs) in the NIC EEPROM.
        !            62:  * If the last EEPROM block is not otherwise filled, we tell
        !            63:  * iPXE it may store NonVolatile Options (nvo) there.
        !            64:  */
        !            65: 
        !            66: /*
        !            67:  * Debugging levels:
        !            68:  *     - DBG() is for any errors, i.e. failed alloc_iob(), malloc_dma(),
        !            69:  *       TX overflow, corrupted packets, ...
        !            70:  *     - DBG2() is for successful events, like packet received,
        !            71:  *       packet transmitted, and other general notifications.
        !            72:  *     - DBGP() prints the name of each called function on entry
        !            73:  */
        !            74: 
        !            75: #include <stdint.h>
        !            76: 
        !            77: #include <byteswap.h>
        !            78: #include <errno.h>
        !            79: #include <ipxe/ethernet.h>
        !            80: #include <ipxe/if_ether.h>
        !            81: #include <ipxe/iobuf.h>
        !            82: #include <ipxe/malloc.h>
        !            83: #include <ipxe/netdevice.h>
        !            84: #include <ipxe/nvo.h>
        !            85: #include <ipxe/nvs.h>
        !            86: #include <ipxe/pci.h>
        !            87: #include <ipxe/timer.h>
        !            88: 
        !            89: #include "myri10ge_mcp.h"
        !            90: 
        !            91: /****************************************************************
        !            92:  * Forward declarations
        !            93:  ****************************************************************/
        !            94: 
        !            95: /* PCI driver entry points */
        !            96: 
        !            97: static int     myri10ge_pci_probe ( struct pci_device* );
        !            98: static void    myri10ge_pci_remove ( struct pci_device* );
        !            99: 
        !           100: /* Network device operations */
        !           101: 
        !           102: static void    myri10ge_net_close ( struct net_device* );
        !           103: static void    myri10ge_net_irq ( struct net_device*, int enable );
        !           104: static int     myri10ge_net_open ( struct net_device* );
        !           105: static void    myri10ge_net_poll ( struct net_device* );
        !           106: static int     myri10ge_net_transmit ( struct net_device*, struct io_buffer* );
        !           107: 
        !           108: /****************************************************************
        !           109:  * Constants
        !           110:  ****************************************************************/
        !           111: 
        !           112: /* Maximum ring indices, used to wrap ring indices.  These must be 2**N-1. */
        !           113: 
        !           114: #define MYRI10GE_TRANSMIT_WRAP                  1U
        !           115: #define MYRI10GE_RECEIVE_WRAP                   7U
        !           116: #define MYRI10GE_RECEIVE_COMPLETION_WRAP        31U
        !           117: 
        !           118: /****************************************************************
        !           119:  * Driver internal data types.
        !           120:  ****************************************************************/
        !           121: 
        !           122: /* Structure holding all DMA buffers for a NIC, which we will
        !           123:    allocated as contiguous read/write DMAable memory when the NIC is
        !           124:    initialized. */
        !           125: 
        !           126: struct myri10ge_dma_buffers
        !           127: {
        !           128:        /* The NIC DMAs receive completion notifications into this ring */
        !           129: 
        !           130:        mcp_slot_t receive_completion[1+MYRI10GE_RECEIVE_COMPLETION_WRAP];
        !           131: 
        !           132:        /* Interrupt details are DMAd here before interrupting. */
        !           133: 
        !           134:        mcp_irq_data_t irq_data; /* 64B */
        !           135: 
        !           136:        /* NIC command completion status is DMAd here. */
        !           137: 
        !           138:        mcp_cmd_response_t command_response; /* 8B */
        !           139: };
        !           140: 
        !           141: struct myri10ge_private
        !           142: {
        !           143:        /* Interrupt support */
        !           144: 
        !           145:        uint32  *irq_claim;     /* in NIC SRAM */
        !           146:        uint32  *irq_deassert;  /* in NIC SRAM */
        !           147: 
        !           148:        /* DMA buffers. */
        !           149: 
        !           150:        struct myri10ge_dma_buffers     *dma;
        !           151: 
        !           152:        /*
        !           153:         * Transmit state.
        !           154:         *
        !           155:         * The counts here are uint32 for easy comparison with
        !           156:         * priv->dma->irq_data.send_done_count and with each other.
        !           157:         */
        !           158: 
        !           159:        mcp_kreq_ether_send_t   *transmit_ring; /* in NIC SRAM */
        !           160:        uint32                   transmit_ring_wrap;
        !           161:        uint32                   transmits_posted;
        !           162:        uint32                   transmits_done;
        !           163:        struct io_buffer        *transmit_iob[1 + MYRI10GE_TRANSMIT_WRAP];
        !           164: 
        !           165:        /*
        !           166:         * Receive state.
        !           167:         */
        !           168: 
        !           169:        mcp_kreq_ether_recv_t   *receive_post_ring;     /* in NIC SRAM */
        !           170:        unsigned int             receive_post_ring_wrap;
        !           171:        unsigned int             receives_posted;
        !           172:        unsigned int             receives_done;
        !           173:        struct io_buffer        *receive_iob[1 + MYRI10GE_RECEIVE_WRAP];
        !           174: 
        !           175:        /* Address for writing commands to the firmware.
        !           176:           BEWARE: the value must be written 32 bits at a time. */
        !           177: 
        !           178:        mcp_cmd_t       *command;
        !           179: 
        !           180:        /*
        !           181:         * Nonvolatile Storage for configuration options.
        !           182:         */
        !           183: 
        !           184:        struct nvs_device       nvs;
        !           185:        struct nvo_block        nvo;
        !           186:        unsigned int            nvo_registered;
        !           187: 
        !           188:        /* Cached PCI capability locations. */
        !           189: 
        !           190:        uint8                   pci_cap_vs;
        !           191: };
        !           192: 
        !           193: /****************************************************************
        !           194:  * Driver internal functions.
        !           195:  ****************************************************************/
        !           196: 
        !           197: /* Print ring status when debugging.  Use this only after a printed
        !           198:    value changes. */
        !           199: 
        !           200: #define DBG2_RINGS( priv )                                             \
        !           201:        DBG2 ( "tx %x/%x rx %x/%x in %s() \n",                          \
        !           202:               ( priv ) ->transmits_done, ( priv ) -> transmits_posted, \
        !           203:               ( priv ) ->receives_done, ( priv ) -> receives_posted,   \
        !           204:               __FUNCTION__ )
        !           205: 
        !           206: /*
        !           207:  * Return a pointer to the driver private data for a network device.
        !           208:  *
        !           209:  * @v netdev   Network device created by this driver.
        !           210:  * @ret priv   The corresponding driver private data.
        !           211:  */
        !           212: static inline struct myri10ge_private *myri10ge_priv ( struct net_device *nd )
        !           213: {
        !           214:        /* Our private data always follows the network device in memory,
        !           215:           since we use alloc_netdev() to allocate the storage. */
        !           216: 
        !           217:        return ( struct myri10ge_private * ) ( nd + 1 );
        !           218: }
        !           219: 
        !           220: /*
        !           221:  * Convert a Myri10ge driver private data pointer to a netdev pointer.
        !           222:  *
        !           223:  * @v p                Myri10ge device private data.
        !           224:  * @ret r      The corresponding network device.
        !           225:  */
        !           226: static inline struct net_device *myri10ge_netdev ( struct myri10ge_private *p )
        !           227: {
        !           228:        return ( ( struct net_device * ) p ) - 1;
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * Convert a network device pointer to a PCI device pointer.
        !           233:  *
        !           234:  * @v netdev   A Network Device.
        !           235:  * @ret r      The corresponding PCI device.
        !           236:  */
        !           237: static inline struct pci_device *myri10ge_pcidev ( struct net_device *netdev )
        !           238: {
        !           239:        return container_of (netdev->dev, struct pci_device, dev);
        !           240: }
        !           241: 
        !           242: /*
        !           243:  * Pass a receive buffer to the NIC to be filled.
        !           244:  *
        !           245:  * @v priv     The network device to receive the buffer.
        !           246:  * @v iob      The I/O buffer to fill.
        !           247:  *
        !           248:  * Receive buffers are filled in FIFO order.
        !           249:  */
        !           250: static void myri10ge_post_receive ( struct myri10ge_private *priv,
        !           251:                                    struct io_buffer *iob )
        !           252: {
        !           253:        unsigned int             receives_posted;
        !           254:        mcp_kreq_ether_recv_t   *request;
        !           255: 
        !           256:        /* Record the posted I/O buffer, to be passed to netdev_rx() on
        !           257:           receive. */
        !           258: 
        !           259:        receives_posted = priv->receives_posted;
        !           260:        priv->receive_iob[receives_posted & MYRI10GE_RECEIVE_WRAP] = iob;
        !           261: 
        !           262:        /* Post the receive. */
        !           263: 
        !           264:        request = &priv->receive_post_ring[receives_posted
        !           265:                                           & priv->receive_post_ring_wrap];
        !           266:        request->addr_high = 0;
        !           267:        wmb();
        !           268:        request->addr_low = htonl ( virt_to_bus ( iob->data ) );
        !           269:        priv->receives_posted = ++receives_posted;
        !           270: }
        !           271: 
        !           272: /*
        !           273:  * Execute a command on the NIC.
        !           274:  *
        !           275:  * @v priv     NIC to perform the command.
        !           276:  * @v cmd      The command to perform.
        !           277:  * @v data     I/O copy buffer for parameters/results
        !           278:  * @ret rc     0 on success, else an error code.
        !           279:  */
        !           280: static int myri10ge_command ( struct myri10ge_private *priv,
        !           281:                              uint32 cmd,
        !           282:                              uint32 data[3] )
        !           283: {
        !           284:        int                              i;
        !           285:        mcp_cmd_t                       *command;
        !           286:        uint32                           result;
        !           287:        unsigned int                     slept_ms;
        !           288:        volatile mcp_cmd_response_t     *response;
        !           289: 
        !           290:        DBGP ( "myri10ge_command ( ,%d, ) \n", cmd );
        !           291:        command = priv->command;
        !           292:        response = &priv->dma->command_response;
        !           293: 
        !           294:        /* Mark the command as incomplete. */
        !           295: 
        !           296:        response->result = 0xFFFFFFFF;
        !           297: 
        !           298:        /* Pass the command to the NIC. */
        !           299: 
        !           300:        command->cmd                = htonl ( cmd );
        !           301:        command->data0              = htonl ( data[0] );
        !           302:        command->data1              = htonl ( data[1] );
        !           303:        command->data2              = htonl ( data[2] );
        !           304:        command->response_addr.high = 0;
        !           305:        command->response_addr.low
        !           306:                = htonl ( virt_to_bus ( &priv->dma->command_response ) );
        !           307:        for ( i=0; i<36; i+=4 )
        !           308:                * ( uint32 * ) &command->pad[i] = 0;
        !           309:        wmb();
        !           310:        * ( uint32 * ) &command->pad[36] = 0;
        !           311: 
        !           312:        /* Wait up to 2 seconds for a response. */
        !           313: 
        !           314:        for ( slept_ms=0; slept_ms<2000; slept_ms++ ) {
        !           315:                result = response->result;
        !           316:                if ( result == 0 ) {
        !           317:                        data[0] = ntohl ( response->data );
        !           318:                        return 0;
        !           319:                } else if ( result != 0xFFFFFFFF ) {
        !           320:                        DBG ( "cmd%d:0x%x\n",
        !           321:                              cmd,
        !           322:                              ntohl ( response->result ) );
        !           323:                        return -EIO;
        !           324:                }
        !           325:                udelay ( 1000 );
        !           326:                rmb();
        !           327:        }
        !           328:        DBG ( "cmd%d:timed out\n", cmd );
        !           329:        return -ETIMEDOUT;
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * Handle any pending interrupt.
        !           334:  *
        !           335:  * @v netdev           Device being polled for interrupts.
        !           336:  *
        !           337:  * This is called periodically to let the driver check for interrupts.
        !           338:  */
        !           339: static void myri10ge_interrupt_handler ( struct net_device *netdev )
        !           340: {
        !           341:        struct myri10ge_private *priv;
        !           342:        mcp_irq_data_t          *irq_data;
        !           343:        uint8                    valid;
        !           344: 
        !           345:        priv = myri10ge_priv ( netdev );
        !           346:        irq_data = &priv->dma->irq_data;
        !           347: 
        !           348:        /* Return if there was no interrupt. */
        !           349: 
        !           350:        rmb();
        !           351:        valid = irq_data->valid;
        !           352:        if ( !valid )
        !           353:                return;
        !           354:        DBG2 ( "irq " );
        !           355: 
        !           356:        /* Tell the NIC to deassert the interrupt and clear
        !           357:           irq_data->valid.*/
        !           358: 
        !           359:        *priv->irq_deassert = 0;        /* any value is OK. */
        !           360:        mb();
        !           361: 
        !           362:        /* Handle any new receives. */
        !           363: 
        !           364:        if ( valid & 1 ) {
        !           365: 
        !           366:                /* Pass the receive interrupt token back to the NIC. */
        !           367: 
        !           368:                DBG2 ( "rx " );
        !           369:                *priv->irq_claim = htonl ( 3 );
        !           370:                wmb();
        !           371:        }
        !           372: 
        !           373:        /* Handle any sent packet by freeing its I/O buffer, now that
        !           374:           we know it has been DMAd. */
        !           375: 
        !           376:        if ( valid & 2 ) {
        !           377:                unsigned int nic_done_count;
        !           378: 
        !           379:                DBG2 ( "snt " );
        !           380:                nic_done_count = ntohl ( priv->dma->irq_data.send_done_count );
        !           381:                while ( priv->transmits_done != nic_done_count ) {
        !           382:                        struct io_buffer *iob;
        !           383: 
        !           384:                        iob = priv->transmit_iob [priv->transmits_done
        !           385:                                                  & MYRI10GE_TRANSMIT_WRAP];
        !           386:                        DBG2 ( "%p ", iob );
        !           387:                        netdev_tx_complete ( netdev, iob );
        !           388:                        ++priv->transmits_done;
        !           389:                }
        !           390:        }
        !           391: 
        !           392:        /* Record any statistics update. */
        !           393: 
        !           394:        if ( irq_data->stats_updated ) {
        !           395: 
        !           396:                /* Update the link status. */
        !           397: 
        !           398:                DBG2 ( "stats " );
        !           399:                if ( ntohl ( irq_data->link_up ) == MXGEFW_LINK_UP )
        !           400:                        netdev_link_up ( netdev );
        !           401:                else
        !           402:                        netdev_link_down ( netdev );
        !           403: 
        !           404:                /* Ignore all error counters from the NIC. */
        !           405:        }
        !           406: 
        !           407:        /* Wait for the interrupt to be deasserted, as indicated by
        !           408:           irq_data->valid, which is set by the NIC after the deassert. */
        !           409: 
        !           410:        DBG2 ( "wait " );
        !           411:        do {
        !           412:                mb();
        !           413:        } while ( irq_data->valid );
        !           414: 
        !           415:        /* Claim the interrupt to enable future interrupt generation. */
        !           416: 
        !           417:        DBG2 ( "claim\n" );
        !           418:        * ( priv->irq_claim + 1 ) = htonl ( 3 );
        !           419:        mb();
        !           420: }
        !           421: 
        !           422: /* Constants for reading the STRING_SPECS via the Myricom
        !           423:    Vendor Specific PCI configuration space capability. */
        !           424: 
        !           425: #define VS_EEPROM_READ_ADDR ( vs + 0x04 )
        !           426: #define VS_EEPROM_READ_DATA ( vs + 0x08 )
        !           427: #define VS_EEPROM_WRITE     ( vs + 0x0C )
        !           428: #define VS_ADDR ( vs + 0x18 )
        !           429: #define VS_DATA ( vs + 0x14 )
        !           430: #define VS_MODE ( vs + 0x10 )
        !           431: #define        VS_MODE_READ32 0x3
        !           432: #define        VS_MODE_LOCATE 0x8
        !           433: #define                VS_LOCATE_STRING_SPECS 0x3
        !           434: #define                VS_MODE_EEPROM_STREAM_WRITE 0xB
        !           435: 
        !           436: /*
        !           437:  * Read MAC address from its 'string specs' via the vendor-specific
        !           438:  * capability.  (This capability allows NIC SRAM and ROM to be read
        !           439:  * before it is mapped.)
        !           440:  *
        !           441:  * @v pci              The device.
        !           442:  * @v vs               Offset of the PCI Vendor-Specific Capability.
        !           443:  * @v mac              Buffer to store the MAC address.
        !           444:  * @ret rc             Returns 0 on success, else an error code.
        !           445:  */
        !           446: static int mac_address_from_string_specs ( struct pci_device *pci,
        !           447:                                           unsigned int vs,
        !           448:                                           uint8 mac[ETH_ALEN] )
        !           449: {
        !           450:        char string_specs[256];
        !           451:        char *ptr, *limit;
        !           452:        char *to = string_specs;
        !           453:        uint32 addr;
        !           454:        uint32 len;
        !           455:        int mac_set = 0;
        !           456: 
        !           457:        /* Locate the String specs in LANai SRAM. */
        !           458: 
        !           459:        pci_write_config_byte ( pci, VS_MODE, VS_MODE_LOCATE );
        !           460:        pci_write_config_dword ( pci, VS_ADDR, VS_LOCATE_STRING_SPECS );
        !           461:        pci_read_config_dword ( pci, VS_ADDR, &addr );
        !           462:        pci_read_config_dword ( pci, VS_DATA, &len );
        !           463:        DBG2 ( "ss@%x,%x\n", addr, len );
        !           464: 
        !           465:        /* Copy in the string specs.  Use 32-bit reads for performance. */
        !           466: 
        !           467:        if ( len > sizeof ( string_specs ) || ( len & 3 ) ) {
        !           468:                pci_write_config_byte ( pci, VS_MODE, 0 );
        !           469:                DBG ( "SS too big\n" );
        !           470:                return -ENOTSUP;
        !           471:        }
        !           472: 
        !           473:        pci_write_config_byte ( pci, VS_MODE, VS_MODE_READ32 );
        !           474:        while ( len >= 4 ) {
        !           475:                uint32 tmp;
        !           476: 
        !           477:                pci_write_config_byte ( pci, VS_ADDR, addr );
        !           478:                pci_read_config_dword ( pci, VS_DATA, &tmp );
        !           479:                tmp = ntohl ( tmp );
        !           480:                memcpy ( to, &tmp, 4 );
        !           481:                to += 4;
        !           482:                addr += 4;
        !           483:                len -= 4;
        !           484:        }
        !           485:        pci_write_config_byte ( pci, VS_MODE, 0 );
        !           486: 
        !           487:        /* Parse the string specs. */
        !           488: 
        !           489:        DBG2 ( "STRING_SPECS:\n" );
        !           490:        ptr = string_specs;
        !           491:        limit = string_specs + sizeof ( string_specs );
        !           492:        while ( *ptr != '\0' && ptr < limit ) {
        !           493:                DBG2 ( "%s\n", ptr );
        !           494:                if ( memcmp ( ptr, "MAC=", 4 ) == 0 ) {
        !           495:                        unsigned int i;
        !           496: 
        !           497:                        ptr += 4;
        !           498:                        for ( i=0; i<6; i++ ) {
        !           499:                                if ( ( ptr + 2 ) > limit ) {
        !           500:                                        DBG ( "bad MAC addr\n" );
        !           501:                                        return -ENOTSUP;
        !           502:                                }
        !           503:                                mac[i] = strtoul ( ptr, &ptr, 16 );
        !           504:                                ptr += 1;
        !           505:                        }
        !           506:                        mac_set = 1;
        !           507:                }
        !           508:                else
        !           509:                        while ( ptr < limit && *ptr++ );
        !           510:        }
        !           511: 
        !           512:        /* Verify we parsed all we need. */
        !           513: 
        !           514:        if ( !mac_set ) {
        !           515:                DBG ( "no MAC addr\n" );
        !           516:                return -ENOTSUP;
        !           517:        }
        !           518: 
        !           519:        DBG2 ( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           520:               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
        !           521: 
        !           522:        return 0;
        !           523: }
        !           524: 
        !           525: /****************************************************************
        !           526:  * NonVolatile Storage support
        !           527:  ****************************************************************/
        !           528: 
        !           529: /*
        !           530:  * Fill a buffer with data read from nonvolatile storage.
        !           531:  *
        !           532:  * @v nvs      The NonVolatile Storage device to be read.
        !           533:  * @v addr      The first NonVolatile Storage address to be read.
        !           534:  * @v _buf     Pointer to the data buffer to be filled.
        !           535:  * @v len      The number of bytes to copy.
        !           536:  * @ret rc     0 on success, else nonzero.
        !           537:  */
        !           538: static int myri10ge_nvs_read ( struct nvs_device *nvs,
        !           539:                               unsigned int addr,
        !           540:                               void *_buf,
        !           541:                               size_t len )
        !           542: {
        !           543:        struct myri10ge_private *priv =
        !           544:                container_of (nvs, struct myri10ge_private, nvs);
        !           545:        struct pci_device *pci = myri10ge_pcidev ( myri10ge_netdev ( priv ) );
        !           546:        unsigned int vs = priv->pci_cap_vs;
        !           547:        unsigned char *buf = (unsigned char *) _buf;
        !           548:        unsigned int data;
        !           549:        unsigned int i, j;
        !           550: 
        !           551:        DBGP ( "myri10ge_nvs_read\n" );
        !           552: 
        !           553:        /* Issue the first read address. */
        !           554: 
        !           555:        pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 3, addr>>16 );
        !           556:        pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 2, addr>>8 );
        !           557:        pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
        !           558:        addr++;
        !           559: 
        !           560:        /* Issue all the reads, and harvest the results every 4th issue. */
        !           561: 
        !           562:        for ( i=0; i<len; ++i,addr++ ) {
        !           563: 
        !           564:                /* Issue the next read address, updating only the
        !           565:                   bytes that need updating.  We always update the
        !           566:                   LSB, which triggers the read. */
        !           567: 
        !           568:                if ( ( addr & 0xff ) == 0 ) {
        !           569:                        if ( ( addr & 0xffff ) == 0 ) {
        !           570:                                pci_write_config_byte ( pci,
        !           571:                                                        VS_EEPROM_READ_ADDR + 3,
        !           572:                                                        addr >> 16 );
        !           573:                        }
        !           574:                        pci_write_config_byte ( pci,
        !           575:                                                VS_EEPROM_READ_ADDR + 2,
        !           576:                                                addr >> 8 );
        !           577:                }
        !           578:                pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
        !           579: 
        !           580:                /* If 4 data bytes are available, read them with a single read. */
        !           581: 
        !           582:                if ( ( i & 3 ) == 3 ) {
        !           583:                        pci_read_config_dword ( pci,
        !           584:                                                VS_EEPROM_READ_DATA,
        !           585:                                                &data );
        !           586:                        for ( j=0; j<4; j++ ) {
        !           587:                                buf[i-j] = data;
        !           588:                                data >>= 8;
        !           589:                        }
        !           590:                }
        !           591:        }
        !           592: 
        !           593:        /* Harvest any remaining results. */
        !           594: 
        !           595:        if ( ( i & 3 ) != 0 ) {
        !           596:                pci_read_config_dword ( pci, VS_EEPROM_READ_DATA, &data );
        !           597:                for ( j=1; j<=(i&3); j++ ) {
        !           598:                        buf[i-j] = data;
        !           599:                        data >>= 8;
        !           600:                }
        !           601:        }
        !           602: 
        !           603:        DBGP_HDA ( addr - len, _buf, len );
        !           604:        return 0;
        !           605: }
        !           606: 
        !           607: /*
        !           608:  * Write a buffer into nonvolatile storage.
        !           609:  *
        !           610:  * @v nvs      The NonVolatile Storage device to be written.
        !           611:  * @v address   The NonVolatile Storage address to be written.
        !           612:  * @v _buf     Pointer to the data to be written.
        !           613:  * @v len      Length of the buffer to be written.
        !           614:  * @ret rc     0 on success, else nonzero.
        !           615:  */
        !           616: static int myri10ge_nvs_write ( struct nvs_device *nvs,
        !           617:                                unsigned int addr,
        !           618:                                const void *_buf,
        !           619:                                size_t len )
        !           620: {
        !           621:        struct myri10ge_private *priv =
        !           622:                container_of (nvs, struct myri10ge_private, nvs);
        !           623:        struct pci_device *pci = myri10ge_pcidev ( myri10ge_netdev ( priv ) );
        !           624:        unsigned int vs = priv->pci_cap_vs;
        !           625:        const unsigned char *buf = (const unsigned char *)_buf;
        !           626:        unsigned int i;
        !           627:        uint8 verify;
        !           628: 
        !           629:        DBGP ( "nvs_write " );
        !           630:        DBGP_HDA ( addr, _buf, len );
        !           631: 
        !           632:        /* Start erase of the NonVolatile Options block. */
        !           633: 
        !           634:        DBGP ( "erasing " );
        !           635:        pci_write_config_dword ( pci, VS_EEPROM_WRITE, ( addr << 8 ) | 0xff );
        !           636: 
        !           637:        /* Wait for erase to complete. */
        !           638: 
        !           639:        DBGP ( "waiting " );
        !           640:        pci_read_config_byte ( pci, VS_EEPROM_READ_DATA, &verify );
        !           641:        while ( verify != 0xff ) {
        !           642:                pci_write_config_byte ( pci, VS_EEPROM_READ_ADDR + 1, addr );
        !           643:                pci_read_config_byte ( pci, VS_EEPROM_READ_DATA, &verify );
        !           644:        }
        !           645: 
        !           646:        /* Write the data one byte at a time. */
        !           647: 
        !           648:        DBGP ( "writing " );
        !           649:        pci_write_config_byte ( pci, VS_MODE, VS_MODE_EEPROM_STREAM_WRITE );
        !           650:        pci_write_config_dword ( pci, VS_ADDR, addr );
        !           651:        for (i=0; i<len; i++, addr++)
        !           652:                pci_write_config_byte ( pci, VS_DATA, buf[i] );
        !           653:        pci_write_config_dword ( pci, VS_ADDR, 0xffffffff );
        !           654:        pci_write_config_byte ( pci, VS_MODE, 0 );
        !           655: 
        !           656:        DBGP ( "done\n" );
        !           657:        return 0;
        !           658: }
        !           659: 
        !           660: /*
        !           661:  * Initialize NonVolatile storage support for a device.
        !           662:  *
        !           663:  * @v priv     Device private data for the device.
        !           664:  * @ret rc     0 on success, else an error code.
        !           665:  */
        !           666: 
        !           667: static int myri10ge_nv_init ( struct myri10ge_private *priv )
        !           668: {
        !           669:        int rc;
        !           670:        struct myri10ge_eeprom_header
        !           671:        {
        !           672:                uint8 __jump[8];
        !           673:                uint32 eeprom_len;
        !           674:                uint32 eeprom_segment_len;
        !           675:                uint32 mcp1_offset;
        !           676:                uint32 mcp2_offset;
        !           677:                uint32 version;
        !           678:        } hdr;
        !           679:        uint32 mcp2_len;
        !           680:        unsigned int nvo_fragment_pos;
        !           681: 
        !           682:        DBGP ( "myri10ge_nv_init\n" );
        !           683: 
        !           684:        /* Read the EEPROM header, and byteswap the fields we will use.
        !           685:           This is safe even though priv->nvs is not yet initialized. */
        !           686: 
        !           687:        rc = myri10ge_nvs_read ( &priv->nvs, 0, &hdr, sizeof ( hdr ) );
        !           688:        if ( rc ) {
        !           689:                DBG ( "EEPROM header unreadable\n" );
        !           690:                return rc;
        !           691:        }
        !           692:        hdr.eeprom_len         = ntohl ( hdr.eeprom_len );
        !           693:        hdr.eeprom_segment_len = ntohl ( hdr.eeprom_segment_len );
        !           694:        hdr.mcp2_offset        = ntohl ( hdr.mcp2_offset );
        !           695:        hdr.version            = ntohl ( hdr.version );
        !           696:        DBG2 ( "eelen:%xh seglen:%xh mcp2@%xh ver%d\n", hdr.eeprom_len,
        !           697:               hdr.eeprom_segment_len, hdr.mcp2_offset, hdr.version );
        !           698: 
        !           699:        /* If the firmware does not support EEPROM writes, simply return. */
        !           700: 
        !           701:        if ( hdr.version < 1 ) {
        !           702:                DBG ( "No EEPROM write support\n" );
        !           703:                return 0;
        !           704:        }
        !           705: 
        !           706:        /* Read the length of MCP2. */
        !           707: 
        !           708:        rc = myri10ge_nvs_read ( &priv->nvs, hdr.mcp2_offset, &mcp2_len, 4 );
        !           709:        mcp2_len = ntohl ( mcp2_len );
        !           710:        DBG2 ( "mcp2len:%xh\n", mcp2_len );
        !           711: 
        !           712:        /* Determine the position of the NonVolatile Options fragment and
        !           713:           simply return if it overlaps other data. */
        !           714: 
        !           715:        nvo_fragment_pos = hdr.eeprom_len -  hdr.eeprom_segment_len;
        !           716:        if ( hdr.mcp2_offset + mcp2_len > nvo_fragment_pos ) {
        !           717:                DBG ( "EEPROM full\n" );
        !           718:                return 0;
        !           719:        }
        !           720: 
        !           721:        /* Initilize NonVolatile Storage state. */
        !           722: 
        !           723:        priv->nvs.word_len_log2 = 0;
        !           724:        priv->nvs.size          = hdr.eeprom_len;
        !           725:        priv->nvs.block_size    = hdr.eeprom_segment_len;
        !           726:        priv->nvs.read          = myri10ge_nvs_read;
        !           727:        priv->nvs.write         = myri10ge_nvs_write;
        !           728: 
        !           729:        /* Register the NonVolatile Options storage. */
        !           730: 
        !           731:        nvo_init ( &priv->nvo,
        !           732:                   &priv->nvs,
        !           733:                   nvo_fragment_pos, 0x200,
        !           734:                   NULL,
        !           735:                   & myri10ge_netdev (priv) -> refcnt );
        !           736:        rc = register_nvo ( &priv->nvo,
        !           737:                            netdev_settings ( myri10ge_netdev ( priv ) ) );
        !           738:        if ( rc ) {
        !           739:                DBG ("register_nvo failed");
        !           740:                return rc;
        !           741:        }
        !           742: 
        !           743:        priv->nvo_registered = 1;
        !           744:        DBG2 ( "NVO supported\n" );
        !           745:        return 0;
        !           746: }
        !           747: 
        !           748: void
        !           749: myri10ge_nv_fini ( struct myri10ge_private *priv )
        !           750: {
        !           751:        /* Simply return if nonvolatile access is not supported. */
        !           752: 
        !           753:        if ( 0 == priv->nvo_registered )
        !           754:                return;
        !           755: 
        !           756:        unregister_nvo ( &priv->nvo );
        !           757: }
        !           758: 
        !           759: /****************************************************************
        !           760:  * iPXE PCI Device Driver API functions
        !           761:  ****************************************************************/
        !           762: 
        !           763: /*
        !           764:  * Initialize the PCI device.
        !           765:  *
        !           766:  * @v pci              The device's associated pci_device structure.
        !           767:  * @v id               The PCI device + vendor id.
        !           768:  * @ret rc             Returns zero if successfully initialized.
        !           769:  *
        !           770:  * This function is called very early on, while iPXE is initializing.
        !           771:  * This is a iPXE PCI Device Driver API function.
        !           772:  */
        !           773: static int myri10ge_pci_probe ( struct pci_device *pci )
        !           774: {
        !           775:        static struct net_device_operations myri10ge_operations = {
        !           776:                .open     = myri10ge_net_open,
        !           777:                .close    = myri10ge_net_close,
        !           778:                .transmit = myri10ge_net_transmit,
        !           779:                .poll     = myri10ge_net_poll,
        !           780:                .irq      = myri10ge_net_irq
        !           781:        };
        !           782: 
        !           783:        const char *dbg;
        !           784:        int rc;
        !           785:        struct net_device *netdev;
        !           786:        struct myri10ge_private *priv;
        !           787: 
        !           788:        DBGP ( "myri10ge_pci_probe: " );
        !           789: 
        !           790:        netdev = alloc_etherdev ( sizeof ( *priv ) );
        !           791:        if ( !netdev ) {
        !           792:                rc = -ENOMEM;
        !           793:                dbg = "alloc_etherdev";
        !           794:                goto abort_with_nothing;
        !           795:        }
        !           796: 
        !           797:        netdev_init ( netdev, &myri10ge_operations );
        !           798:        priv = myri10ge_priv ( netdev );
        !           799: 
        !           800:        pci_set_drvdata ( pci, netdev );
        !           801:        netdev->dev = &pci->dev;
        !           802: 
        !           803:        /* Make sure interrupts are disabled. */
        !           804: 
        !           805:        myri10ge_net_irq ( netdev, 0 );
        !           806: 
        !           807:        /* Find the PCI Vendor-Specific capability. */
        !           808: 
        !           809:        priv->pci_cap_vs = pci_find_capability ( pci , PCI_CAP_ID_VNDR );
        !           810:        if ( 0 == priv->pci_cap_vs ) {
        !           811:                rc = -ENOTSUP;
        !           812:                dbg = "no_vs";
        !           813:                goto abort_with_netdev_init;
        !           814:        }
        !           815: 
        !           816:        /* Read the NIC HW address. */
        !           817: 
        !           818:        rc = mac_address_from_string_specs ( pci,
        !           819:                                             priv->pci_cap_vs,
        !           820:                                             netdev->hw_addr );
        !           821:        if ( rc ) {
        !           822:                dbg = "mac_from_ss";
        !           823:                goto abort_with_netdev_init;
        !           824:        }
        !           825:        DBGP ( "mac " );
        !           826: 
        !           827:        /* Enable bus master, etc. */
        !           828: 
        !           829:        adjust_pci_device ( pci );
        !           830:        DBGP ( "pci " );
        !           831: 
        !           832:        /* Register the initialized network device. */
        !           833: 
        !           834:        rc = register_netdev ( netdev );
        !           835:        if ( rc ) {
        !           836:                dbg = "register_netdev";
        !           837:                goto abort_with_netdev_init;
        !           838:        }
        !           839: 
        !           840:        /* Initialize NonVolatile Storage support. */
        !           841: 
        !           842:        rc = myri10ge_nv_init ( priv );
        !           843:        if ( rc ) {
        !           844:                dbg = "myri10ge_nv_init";
        !           845:                goto abort_with_registered_netdev;
        !           846:        }
        !           847: 
        !           848:        DBGP ( "done\n" );
        !           849: 
        !           850:        return 0;
        !           851: 
        !           852: abort_with_registered_netdev:
        !           853:        unregister_netdev ( netdev );
        !           854: abort_with_netdev_init:
        !           855:        netdev_nullify ( netdev );
        !           856:        netdev_put ( netdev );
        !           857: abort_with_nothing:
        !           858:        DBG ( "%s:%s\n", dbg, strerror ( rc ) );
        !           859:        return rc;
        !           860: }
        !           861: 
        !           862: /*
        !           863:  * Remove a device from the PCI device list.
        !           864:  *
        !           865:  * @v pci              PCI device to remove.
        !           866:  *
        !           867:  * This is a PCI Device Driver API function.
        !           868:  */
        !           869: static void myri10ge_pci_remove ( struct pci_device *pci )
        !           870: {
        !           871:        struct net_device       *netdev;
        !           872: 
        !           873:        DBGP ( "myri10ge_pci_remove\n" );
        !           874:        netdev = pci_get_drvdata ( pci );
        !           875: 
        !           876:        myri10ge_nv_fini ( myri10ge_priv ( netdev ) );
        !           877:        unregister_netdev ( netdev );
        !           878:        netdev_nullify ( netdev );
        !           879:        netdev_put ( netdev );
        !           880: }
        !           881: 
        !           882: /****************************************************************
        !           883:  * iPXE Network Device Driver Operations
        !           884:  ****************************************************************/
        !           885: 
        !           886: /*
        !           887:  * Close a network device.
        !           888:  *
        !           889:  * @v netdev           Device to close.
        !           890:  *
        !           891:  * This is a iPXE Network Device Driver API function.
        !           892:  */
        !           893: static void myri10ge_net_close ( struct net_device *netdev )
        !           894: {
        !           895:        struct myri10ge_private *priv;
        !           896:        uint32                   data[3];
        !           897: 
        !           898:        DBGP ( "myri10ge_net_close\n" );
        !           899:        priv = myri10ge_priv ( netdev );
        !           900: 
        !           901:        /* disable interrupts */
        !           902: 
        !           903:        myri10ge_net_irq ( netdev, 0 );
        !           904: 
        !           905:        /* Reset the NIC interface, so we won't get any more events from
        !           906:           the NIC. */
        !           907: 
        !           908:        myri10ge_command ( priv, MXGEFW_CMD_RESET, data );
        !           909: 
        !           910:        /* Free receive buffers that were never filled. */
        !           911: 
        !           912:        while ( priv->receives_done != priv->receives_posted ) {
        !           913:                free_iob ( priv->receive_iob[priv->receives_done
        !           914:                                             & MYRI10GE_RECEIVE_WRAP] );
        !           915:                ++priv->receives_done;
        !           916:        }
        !           917: 
        !           918:        /* Release DMAable memory. */
        !           919: 
        !           920:        free_dma ( priv->dma, sizeof ( *priv->dma ) );
        !           921: 
        !           922:        /* Erase all state from the open. */
        !           923: 
        !           924:        memset ( priv, 0, sizeof ( *priv ) );
        !           925: 
        !           926:        DBG2_RINGS ( priv );
        !           927: }
        !           928: 
        !           929: /*
        !           930:  * Enable or disable IRQ masking.
        !           931:  *
        !           932:  * @v netdev           Device to control.
        !           933:  * @v enable           Zero to mask off IRQ, non-zero to enable IRQ.
        !           934:  *
        !           935:  * This is a iPXE Network Driver API function.
        !           936:  */
        !           937: static void myri10ge_net_irq ( struct net_device *netdev, int enable )
        !           938: {
        !           939:        struct pci_device       *pci_dev;
        !           940:        uint16                   val;
        !           941: 
        !           942:        DBGP ( "myri10ge_net_irq\n" );
        !           943:        pci_dev = ( struct pci_device * ) netdev->dev;
        !           944: 
        !           945:        /* Adjust the Interrupt Disable bit in the Command register of the
        !           946:           PCI Device. */
        !           947: 
        !           948:        pci_read_config_word ( pci_dev, PCI_COMMAND, &val );
        !           949:        if ( enable )
        !           950:                val &= ~PCI_COMMAND_INTX_DISABLE;
        !           951:        else
        !           952:                val |= PCI_COMMAND_INTX_DISABLE;
        !           953:        pci_write_config_word ( pci_dev, PCI_COMMAND, val );
        !           954: }
        !           955: 
        !           956: /*
        !           957:  * Opens a network device.
        !           958:  *
        !           959:  * @v netdev           Device to be opened.
        !           960:  * @ret rc             Non-zero if failed to open.
        !           961:  *
        !           962:  * This enables tx and rx on the device.
        !           963:  * This is a iPXE Network Device Driver API function.
        !           964:  */
        !           965: static int myri10ge_net_open ( struct net_device *netdev )
        !           966: {
        !           967:        const char              *dbg;   /* printed upon error return */
        !           968:        int                      rc;
        !           969:        struct io_buffer        *iob;
        !           970:        struct myri10ge_private *priv;
        !           971:        uint32                   data[3];
        !           972:        struct pci_device       *pci_dev;
        !           973:        void                    *membase;
        !           974: 
        !           975:        DBGP ( "myri10ge_net_open\n" );
        !           976:        priv    = myri10ge_priv ( netdev );
        !           977:        pci_dev = ( struct pci_device * ) netdev->dev;
        !           978:        membase = phys_to_virt ( pci_dev->membase );
        !           979: 
        !           980:        /* Compute address for passing commands to the firmware. */
        !           981: 
        !           982:        priv->command = membase + MXGEFW_ETH_CMD;
        !           983: 
        !           984:        /* Ensure interrupts are disabled. */
        !           985: 
        !           986:        myri10ge_net_irq ( netdev, 0 );
        !           987: 
        !           988:        /* Allocate cleared DMAable buffers. */
        !           989: 
        !           990:        priv->dma = malloc_dma ( sizeof ( *priv->dma ) , 128 );
        !           991:        if ( !priv->dma ) {
        !           992:                rc = -ENOMEM;
        !           993:                dbg = "DMA";
        !           994:                goto abort_with_nothing;
        !           995:        }
        !           996:        memset ( priv->dma, 0, sizeof ( *priv->dma ) );
        !           997: 
        !           998:        /* Simplify following code. */
        !           999: 
        !          1000: #define TRY( prefix, base, suffix ) do {               \
        !          1001:                rc = myri10ge_command ( priv,           \
        !          1002:                                        MXGEFW_         \
        !          1003:                                        ## prefix       \
        !          1004:                                        ## base         \
        !          1005:                                        ## suffix,      \
        !          1006:                                        data );         \
        !          1007:                if ( rc ) {                             \
        !          1008:                        dbg = #base;                    \
        !          1009:                        goto abort_with_dma;            \
        !          1010:                }                                       \
        !          1011:        } while ( 0 )
        !          1012: 
        !          1013:        /* Send a reset command to the card to see if it is alive,
        !          1014:           and to reset its queue state. */
        !          1015: 
        !          1016:        TRY ( CMD_, RESET , );
        !          1017: 
        !          1018:        /* Set the interrupt queue size. */
        !          1019: 
        !          1020:        data[0] = ( (uint32_t)( sizeof ( priv->dma->receive_completion ) )
        !          1021:                    | MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK );
        !          1022:        TRY ( CMD_SET_ , INTRQ_SIZE , );
        !          1023: 
        !          1024:        /* Set the interrupt queue DMA address. */
        !          1025: 
        !          1026:        data[0] = virt_to_bus ( &priv->dma->receive_completion );
        !          1027:        data[1] = 0;
        !          1028:        TRY ( CMD_SET_, INTRQ_DMA, );
        !          1029: 
        !          1030:        /* Get the NIC interrupt claim address. */
        !          1031: 
        !          1032:        TRY ( CMD_GET_, IRQ_ACK, _OFFSET );
        !          1033:        priv->irq_claim = membase + data[0];
        !          1034: 
        !          1035:        /* Get the NIC interrupt assert address. */
        !          1036: 
        !          1037:        TRY ( CMD_GET_, IRQ_DEASSERT, _OFFSET );
        !          1038:        priv->irq_deassert = membase + data[0];
        !          1039: 
        !          1040:        /* Disable interrupt coalescing, which is inappropriate for the
        !          1041:           minimal buffering we provide. */
        !          1042: 
        !          1043:        TRY ( CMD_GET_, INTR_COAL, _DELAY_OFFSET );
        !          1044:        * ( ( uint32 * ) ( membase + data[0] ) ) = 0;
        !          1045: 
        !          1046:        /* Set the NIC mac address. */
        !          1047: 
        !          1048:        data[0] = ( netdev->ll_addr[0] << 24
        !          1049:                    | netdev->ll_addr[1] << 16
        !          1050:                    | netdev->ll_addr[2] << 8
        !          1051:                    | netdev->ll_addr[3] );
        !          1052:        data[1] = ( ( netdev->ll_addr[4] << 8 )
        !          1053:                     | netdev->ll_addr[5] );
        !          1054:        TRY ( SET_ , MAC_ADDRESS , );
        !          1055: 
        !          1056:        /* Enable multicast receives, because some iPXE clients don't work
        !          1057:           without multicast. . */
        !          1058: 
        !          1059:        TRY ( ENABLE_ , ALLMULTI , );
        !          1060: 
        !          1061:        /* Disable Ethernet flow control, so the NIC cannot deadlock the
        !          1062:           network under any circumstances. */
        !          1063: 
        !          1064:        TRY ( DISABLE_ , FLOW , _CONTROL );
        !          1065: 
        !          1066:        /* Compute transmit ring sizes. */
        !          1067: 
        !          1068:        data[0] = 0;            /* slice 0 */
        !          1069:        TRY ( CMD_GET_, SEND_RING, _SIZE );
        !          1070:        priv->transmit_ring_wrap
        !          1071:                = data[0] / sizeof ( mcp_kreq_ether_send_t ) - 1;
        !          1072:        if ( priv->transmit_ring_wrap
        !          1073:             & ( priv->transmit_ring_wrap + 1 ) ) {
        !          1074:                rc = -EPROTO;
        !          1075:                dbg = "TX_RING";
        !          1076:                goto abort_with_dma;
        !          1077:        }
        !          1078: 
        !          1079:        /* Compute receive ring sizes. */
        !          1080: 
        !          1081:        data[0] = 0;            /* slice 0 */
        !          1082:        TRY ( CMD_GET_ , RX_RING , _SIZE );
        !          1083:        priv->receive_post_ring_wrap = data[0] / sizeof ( mcp_dma_addr_t ) - 1;
        !          1084:        if ( priv->receive_post_ring_wrap
        !          1085:             & ( priv->receive_post_ring_wrap + 1 ) ) {
        !          1086:                rc = -EPROTO;
        !          1087:                dbg = "RX_RING";
        !          1088:                goto abort_with_dma;
        !          1089:        }
        !          1090: 
        !          1091:        /* Get NIC transmit ring address. */
        !          1092: 
        !          1093:        data[0] = 0;            /* slice 0. */
        !          1094:        TRY ( CMD_GET_, SEND, _OFFSET );
        !          1095:        priv->transmit_ring = membase + data[0];
        !          1096: 
        !          1097:        /* Get the NIC receive ring address. */
        !          1098: 
        !          1099:        data[0] = 0;            /* slice 0. */
        !          1100:        TRY ( CMD_GET_, SMALL_RX, _OFFSET );
        !          1101:        priv->receive_post_ring = membase + data[0];
        !          1102: 
        !          1103:        /* Set the Nic MTU. */
        !          1104: 
        !          1105:        data[0] = ETH_FRAME_LEN;
        !          1106:        TRY ( CMD_SET_, MTU, );
        !          1107: 
        !          1108:        /* Tell the NIC our buffer sizes. ( We use only small buffers, so we
        !          1109:           set both buffer sizes to the same value, which will force all
        !          1110:           received frames to use small buffers. ) */
        !          1111: 
        !          1112:        data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
        !          1113:        TRY ( CMD_SET_, SMALL_BUFFER, _SIZE );
        !          1114:        data[0] = MXGEFW_PAD + ETH_FRAME_LEN;
        !          1115:        TRY ( CMD_SET_, BIG_BUFFER, _SIZE );
        !          1116: 
        !          1117:         /* Tell firmware where to DMA IRQ data */
        !          1118: 
        !          1119:        data[0] = virt_to_bus ( &priv->dma->irq_data );
        !          1120:        data[1] = 0;
        !          1121:        data[2] = sizeof ( priv->dma->irq_data );
        !          1122:        TRY ( CMD_SET_, STATS_DMA_V2, );
        !          1123: 
        !          1124:        /* Post receives. */
        !          1125: 
        !          1126:        while ( priv->receives_posted <= MYRI10GE_RECEIVE_WRAP ) {
        !          1127: 
        !          1128:                /* Reserve 2 extra bytes at the start of packets, since
        !          1129:                   the firmware always skips the first 2 bytes of the buffer
        !          1130:                   so TCP headers will be aligned. */
        !          1131: 
        !          1132:                iob = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
        !          1133:                if ( !iob ) {
        !          1134:                        rc = -ENOMEM;
        !          1135:                        dbg = "alloc_iob";
        !          1136:                        goto abort_with_receives_posted;
        !          1137:                }
        !          1138:                iob_reserve ( iob, MXGEFW_PAD );
        !          1139:                myri10ge_post_receive ( priv, iob );
        !          1140:        }
        !          1141: 
        !          1142:        /* Bring up the link. */
        !          1143: 
        !          1144:        TRY ( CMD_, ETHERNET_UP, );
        !          1145: 
        !          1146:        DBG2_RINGS ( priv );
        !          1147:        return 0;
        !          1148: 
        !          1149: abort_with_receives_posted:
        !          1150:        while ( priv->receives_posted-- )
        !          1151:                free_iob ( priv->receive_iob[priv->receives_posted] );
        !          1152: abort_with_dma:
        !          1153:        /* Because the link is not up, we don't have to reset the NIC here. */
        !          1154:        free_dma ( priv->dma, sizeof ( *priv->dma ) );
        !          1155: abort_with_nothing:
        !          1156:        /* Erase all signs of the failed open. */
        !          1157:        memset ( priv, 0, sizeof ( *priv ) );
        !          1158:        DBG ( "%s: %s\n", dbg, strerror ( rc ) );
        !          1159:        return ( rc );
        !          1160: }
        !          1161: 
        !          1162: /*
        !          1163:  * This function allows a driver to process events during operation.
        !          1164:  *
        !          1165:  * @v netdev           Device being polled.
        !          1166:  *
        !          1167:  * This is called periodically by iPXE to let the driver check the status of
        !          1168:  * transmitted packets and to allow the driver to check for received packets.
        !          1169:  * This is a iPXE Network Device Driver API function.
        !          1170:  */
        !          1171: static void myri10ge_net_poll ( struct net_device *netdev )
        !          1172: {
        !          1173:        struct io_buffer                *iob;
        !          1174:        struct io_buffer                *replacement;
        !          1175:        struct myri10ge_dma_buffers     *dma;
        !          1176:        struct myri10ge_private         *priv;
        !          1177:        unsigned int                     length;
        !          1178:        unsigned int                     orig_receives_posted;
        !          1179: 
        !          1180:        DBGP ( "myri10ge_net_poll\n" );
        !          1181:        priv = myri10ge_priv ( netdev );
        !          1182:        dma  = priv->dma;
        !          1183: 
        !          1184:        /* Process any pending interrupt. */
        !          1185: 
        !          1186:        myri10ge_interrupt_handler ( netdev );
        !          1187: 
        !          1188:        /* Pass up received frames, but limit ourselves to receives posted
        !          1189:           before this function was called, so we cannot livelock if
        !          1190:           receives are arriving faster than we process them. */
        !          1191: 
        !          1192:        orig_receives_posted = priv->receives_posted;
        !          1193:        while ( priv->receives_done != orig_receives_posted ) {
        !          1194: 
        !          1195:                /* Stop if there is no pending receive. */
        !          1196: 
        !          1197:                length = ntohs ( dma->receive_completion
        !          1198:                                 [priv->receives_done
        !          1199:                                  & MYRI10GE_RECEIVE_COMPLETION_WRAP]
        !          1200:                                 .length );
        !          1201:                if ( length == 0 )
        !          1202:                        break;
        !          1203: 
        !          1204:                /* Allocate a replacement buffer.  If none is available,
        !          1205:                   stop passing up packets until a buffer is available.
        !          1206: 
        !          1207:                   Reserve 2 extra bytes at the start of packets, since
        !          1208:                   the firmware always skips the first 2 bytes of the buffer
        !          1209:                   so TCP headers will be aligned. */
        !          1210: 
        !          1211:                replacement = alloc_iob ( MXGEFW_PAD + ETH_FRAME_LEN );
        !          1212:                if ( !replacement ) {
        !          1213:                        DBG ( "NO RX BUF\n" );
        !          1214:                        break;
        !          1215:                }
        !          1216:                iob_reserve ( replacement, MXGEFW_PAD );
        !          1217: 
        !          1218:                /* Pass up the received frame. */
        !          1219: 
        !          1220:                iob = priv->receive_iob[priv->receives_done
        !          1221:                                        & MYRI10GE_RECEIVE_WRAP];
        !          1222:                iob_put ( iob, length );
        !          1223:                netdev_rx ( netdev, iob );
        !          1224: 
        !          1225:                /* We have consumed the packet, so clear the receive
        !          1226:                   notification. */
        !          1227: 
        !          1228:                dma->receive_completion [priv->receives_done
        !          1229:                                         & MYRI10GE_RECEIVE_COMPLETION_WRAP]
        !          1230:                        .length = 0;
        !          1231:                wmb();
        !          1232: 
        !          1233:                /* Replace the passed-up I/O buffer. */
        !          1234: 
        !          1235:                myri10ge_post_receive ( priv, replacement );
        !          1236:                ++priv->receives_done;
        !          1237:                DBG2_RINGS ( priv );
        !          1238:        }
        !          1239: }
        !          1240: 
        !          1241: /*
        !          1242:  * This transmits a packet.
        !          1243:  *
        !          1244:  * @v netdev           Device to transmit from.
        !          1245:  * @v iobuf            Data to transmit.
        !          1246:  * @ret rc             Non-zero if failed to transmit.
        !          1247:  *
        !          1248:  * This is a iPXE Network Driver API function.
        !          1249:  */
        !          1250: static int myri10ge_net_transmit ( struct net_device *netdev,
        !          1251:                                   struct io_buffer *iobuf )
        !          1252: {
        !          1253:        mcp_kreq_ether_send_t   *kreq;
        !          1254:        size_t                   len;
        !          1255:        struct myri10ge_private *priv;
        !          1256:        uint32                   transmits_posted;
        !          1257: 
        !          1258:        DBGP ( "myri10ge_net_transmit\n" );
        !          1259:        priv = myri10ge_priv ( netdev );
        !          1260: 
        !          1261:        /* Confirm space in the send ring. */
        !          1262: 
        !          1263:        transmits_posted = priv->transmits_posted;
        !          1264:        if ( transmits_posted - priv->transmits_done
        !          1265:             > MYRI10GE_TRANSMIT_WRAP ) {
        !          1266:                DBG ( "TX ring full\n" );
        !          1267:                return -ENOBUFS;
        !          1268:        }
        !          1269: 
        !          1270:        DBG2 ( "TX %p+%zd ", iobuf->data, iob_len ( iobuf ) );
        !          1271:        DBG2_HD ( iobuf->data, 14 );
        !          1272: 
        !          1273:        /* Record the packet being transmitted, so we can later report
        !          1274:           send completion. */
        !          1275: 
        !          1276:        priv->transmit_iob[transmits_posted & MYRI10GE_TRANSMIT_WRAP] = iobuf;
        !          1277: 
        !          1278:        /* Copy and pad undersized frames, because the NIC does not pad,
        !          1279:           and we would rather copy small frames than do a gather. */
        !          1280: 
        !          1281:        len = iob_len ( iobuf );
        !          1282:        if ( len < ETH_ZLEN ) {
        !          1283:                iob_pad ( iobuf, ETH_ZLEN );
        !          1284:                len = ETH_ZLEN;
        !          1285:        }
        !          1286: 
        !          1287:        /* Enqueue the packet by writing a descriptor to the NIC.
        !          1288:           This is a bit tricky because the HW requires 32-bit writes,
        !          1289:           but the structure has smaller fields. */
        !          1290: 
        !          1291:        kreq = &priv->transmit_ring[transmits_posted
        !          1292:                                    & priv->transmit_ring_wrap];
        !          1293:        kreq->addr_high = 0;
        !          1294:        kreq->addr_low = htonl ( virt_to_bus ( iobuf->data ) );
        !          1295:        ( ( uint32 * ) kreq ) [2] = htonl (
        !          1296:                0x0000 << 16     /* pseudo_header_offset */
        !          1297:                | ( len & 0xFFFF ) /* length */
        !          1298:                );
        !          1299:        wmb();
        !          1300:        ( ( uint32 * ) kreq ) [3] = htonl (
        !          1301:                0x00 << 24      /* pad */
        !          1302:                | 0x01 << 16    /* rdma_count */
        !          1303:                | 0x00 << 8     /* cksum_offset */
        !          1304:                | ( MXGEFW_FLAGS_SMALL
        !          1305:                    | MXGEFW_FLAGS_FIRST
        !          1306:                    | MXGEFW_FLAGS_NO_TSO ) /* flags */
        !          1307:                );
        !          1308:        wmb();
        !          1309: 
        !          1310:        /* Mark the slot as consumed and return. */
        !          1311: 
        !          1312:        priv->transmits_posted = ++transmits_posted;
        !          1313:        DBG2_RINGS ( priv );
        !          1314:        return 0;
        !          1315: }
        !          1316: 
        !          1317: static struct pci_device_id myri10ge_nics[] = {
        !          1318:        /* Each of these macros must be a single line to satisfy a script. */
        !          1319:        PCI_ROM ( 0x14c1, 0x0008, "myri10ge", "Myricom 10Gb Ethernet Adapter", 0 ) ,
        !          1320: };
        !          1321: 
        !          1322: struct pci_driver myri10ge_driver __pci_driver = {
        !          1323:        .ids      = myri10ge_nics,
        !          1324:        .id_count = ( sizeof ( myri10ge_nics ) / sizeof ( myri10ge_nics[0] ) ) ,
        !          1325:        .probe    = myri10ge_pci_probe,
        !          1326:        .remove   = myri10ge_pci_remove
        !          1327: };
        !          1328: 
        !          1329: /*
        !          1330:  * Local variables:
        !          1331:  *  c-basic-offset: 8
        !          1332:  *  c-indent-level: 8
        !          1333:  *  tab-width: 8
        !          1334:  * End:
        !          1335:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.