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

1.1     ! root        1: /*
        !             2:  * eepro100.c -- This is a driver for Intel Fast Ethernet Controllers
        !             3:  * (ifec).
        !             4:  *
        !             5:  * Originally written for Etherboot by:
        !             6:  *
        !             7:  *   Copyright (C) AW Computer Systems.
        !             8:  *   written by R.E.Wolff -- [email protected]
        !             9:  *
        !            10:  *   AW Computer Systems is contributing to the free software community
        !            11:  *   by paying for this driver and then putting the result under GPL.
        !            12:  *
        !            13:  *   If you need a Linux device driver, please contact BitWizard for a
        !            14:  *   quote.
        !            15:  *
        !            16:  * This program is free software; you can redistribute it and/or
        !            17:  * modify it under the terms of the GNU General Public License as
        !            18:  * published by the Free Software Foundation; either version 2, or (at
        !            19:  * your option) any later version.
        !            20:  *
        !            21:  * This program is distributed in the hope that it will be useful, but
        !            22:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            23:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            24:  * General Public License for more details.
        !            25:  *
        !            26:  * You should have received a copy of the GNU General Public License
        !            27:  * along with this program; if not, write to the Free Software
        !            28:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            29:  *
        !            30:  *
        !            31:  *              date       version  by      what
        !            32:  *  Written:    May 29 1997  V0.10  REW     Initial revision.
        !            33:  * changes:     May 31 1997  V0.90  REW     Works!
        !            34:  *              Jun 1  1997  V0.91  REW     Cleanup
        !            35:  *              Jun 2  1997  V0.92  REW     Add some code documentation
        !            36:  *              Jul 25 1997  V1.00  REW     Tested by AW to work in a PROM
        !            37:  *                                          Cleanup for publication
        !            38:  *              Dez 11 2004  V1.10  Kiszka  Add RX ring buffer support
        !            39:  *              Jun    2008  v2.0   mdeck   Updated to iPXE. Changed much.
        !            40:  *
        !            41:  * Cleanups and fixes by Thomas Miletich<[email protected]>
        !            42:  *
        !            43:  * This is the etherboot intel etherexpress Pro/100B driver.
        !            44:  *
        !            45:  * It was written from scratch, with Donald Beckers eepro100.c kernel
        !            46:  * driver as a guideline. Mostly the 82557 related definitions and the
        !            47:  * lower level routines have been cut-and-pasted into this source.
        !            48:  *
        !            49:  * The driver was finished before Intel got the NDA out of the closet.
        !            50:  *
        !            51:  * Datasheet is now published and available from 
        !            52:  * ftp://download.intel.com/design/network/manuals/8255X_OpenSDM.pdf
        !            53:  *    - Michael Brown
        !            54:  * */
        !            55: 
        !            56: FILE_LICENCE ( GPL2_OR_LATER );
        !            57: 
        !            58: /*
        !            59:  * General Theory of Operation
        !            60:  *
        !            61:  * Initialization
        !            62:  *
        !            63:  * ifec_pci_probe() is called by iPXE during initialization. Typical NIC
        !            64:  * initialization is performed.  EEPROM data is read.
        !            65:  *
        !            66:  * Network Boot
        !            67:  *
        !            68:  * ifec_net_open() is called by iPXE before attempting to network boot from the
        !            69:  * card.  Here, the Command Unit & Receive Unit are initialized.  The tx & rx
        !            70:  * rings are setup.  The MAC address is programmed and the card is configured.
        !            71:  *
        !            72:  * Transmit
        !            73:  *
        !            74:  * ifec_net_transmit() enqueues a packet in the tx ring - active::tcbs[]  The tx
        !            75:  * ring is composed of TCBs linked to each other into a ring.  A tx request
        !            76:  * fills out the next available TCB with a pointer to the packet data.
        !            77:  * The last enqueued tx is always at active::tcb_head.  Thus, a tx request fills
        !            78:  * out the TCB following tcb_head.
        !            79:  * active::tcb_tail points to the TCB we're awaiting completion of.
        !            80:  * ifec_tx_process() checks tcb_tail, and once complete,
        !            81:  * blindly increments tcb_tail to the next ring TCB.
        !            82:  *
        !            83:  * Receive
        !            84:  *
        !            85:  * priv::rfds[] is an array of Receive Frame Descriptors. The RFDs are linked
        !            86:  * together to form a ring.
        !            87:  * ifec_net_poll() calls ifec_rx_process(), which checks the next RFD for
        !            88:  * data.  If we received a packet, we allocate a new io_buffer and copy the
        !            89:  * packet data into it. If alloc_iob() fails, we don't touch the RFD and try
        !            90:  * again on the next poll.
        !            91:  */
        !            92: 
        !            93: /*
        !            94:  * Debugging levels:
        !            95:  *     - DBG() is for any errors, i.e. failed alloc_iob(), malloc_dma(),
        !            96:  *       TX overflow, corrupted packets, ...
        !            97:  *     - DBG2() is for successful events, like packet received,
        !            98:  *       packet transmitted, and other general notifications.
        !            99:  *     - DBGP() prints the name of each called function on entry
        !           100:  */
        !           101: 
        !           102: #include <stdint.h>
        !           103: #include <byteswap.h>
        !           104: #include <errno.h>
        !           105: #include <stdio.h>
        !           106: #include <unistd.h>
        !           107: #include <ipxe/ethernet.h>
        !           108: #include <ipxe/if_ether.h>
        !           109: #include <ipxe/iobuf.h>
        !           110: #include <ipxe/malloc.h>
        !           111: #include <ipxe/pci.h>
        !           112: #include <ipxe/spi_bit.h>
        !           113: #include <ipxe/timer.h>
        !           114: #include <ipxe/nvs.h>
        !           115: #include <ipxe/threewire.h>
        !           116: #include <ipxe/netdevice.h>
        !           117: #include "eepro100.h"
        !           118: 
        !           119: /****************************** Global data **********************************/
        !           120: 
        !           121: /*
        !           122:  * This is the default configuration command data. The values were copied from
        !           123:  * the Linux kernel initialization for the eepro100.
        !           124:  */
        !           125: static struct ifec_cfg ifec_cfg = {
        !           126:        .status  = 0,
        !           127:        .command = CmdConfigure | CmdSuspend,
        !           128:        .link    = 0,        /* Filled in later */
        !           129:        .byte = { 22,        /* How many bytes in this array */
        !           130:                  ( TX_FIFO << 4 ) | RX_FIFO,  /* Rx & Tx FIFO limits */
        !           131:                  0, 0,                        /* Adaptive Interframe Spacing */
        !           132:                  RX_DMA_COUNT,                /* Rx DMA max byte count */
        !           133:                  TX_DMA_COUNT + 0x80,         /* Tx DMA max byte count */
        !           134:                  0x32,      /* Many bits. */
        !           135:                  0x03,      /* Discard short receive & Underrun retries */
        !           136:                  1,         /* 1=Use MII  0=Use AUI */
        !           137:                  0,
        !           138:                  0x2E,      /* NSAI, Preamble length, & Loopback*/
        !           139:                  0,         /* Linear priority */
        !           140:                  0x60,      /* L PRI MODE & Interframe spacing */
        !           141:                  0, 0xf2,
        !           142:                  0x48,      /* Promiscuous, Broadcast disable, CRS & CDT */
        !           143:                  0, 0x40,
        !           144:                  0xf2,      /* Stripping, Padding, Receive CRC Transfer */
        !           145:                  0x80,      /* 0x40=Force full-duplex, 0x80=Allowfull-duplex*/
        !           146:                  0x3f,      /* Multiple IA */
        !           147:                  0x0D }     /* Multicast all */
        !           148: };
        !           149: 
        !           150: static struct net_device_operations ifec_operations = {
        !           151:        .open     = ifec_net_open,
        !           152:        .close    = ifec_net_close,
        !           153:        .transmit = ifec_net_transmit,
        !           154:        .poll     = ifec_net_poll,
        !           155:        .irq      = ifec_net_irq
        !           156: };
        !           157: 
        !           158: /******************* iPXE PCI Device Driver API functions ********************/
        !           159: 
        !           160: /*
        !           161:  * Initialize the PCI device.
        !           162:  *
        !           163:  * @v pci              The device's associated pci_device structure.
        !           164:  * @v id               The PCI device + vendor id.
        !           165:  * @ret rc             Returns zero if successfully initialized.
        !           166:  *
        !           167:  * This function is called very early on, while iPXE is initializing.
        !           168:  * This is a iPXE PCI Device Driver API function.
        !           169:  */
        !           170: static int ifec_pci_probe ( struct pci_device *pci )
        !           171: {
        !           172:        struct net_device *netdev;
        !           173:        struct ifec_private *priv;
        !           174:        int rc;
        !           175: 
        !           176:        DBGP ( "ifec_pci_probe: " );
        !           177: 
        !           178:        if ( pci->ioaddr == 0 )
        !           179:                return -EINVAL;
        !           180: 
        !           181:        netdev = alloc_etherdev ( sizeof(*priv) );
        !           182:        if ( !netdev )
        !           183:                return -ENOMEM;
        !           184: 
        !           185:        netdev_init ( netdev, &ifec_operations );
        !           186:        priv = netdev->priv;
        !           187: 
        !           188:        pci_set_drvdata ( pci, netdev );
        !           189:        netdev->dev = &pci->dev;
        !           190: 
        !           191:        /* enable bus master, etc */
        !           192:        adjust_pci_device( pci );
        !           193: 
        !           194:        DBGP ( "pci " );
        !           195: 
        !           196:        memset ( priv, 0, sizeof(*priv) );
        !           197:        priv->ioaddr = pci->ioaddr;
        !           198: 
        !           199:        ifec_reset ( netdev );
        !           200:        DBGP ( "reset " );
        !           201: 
        !           202:        ifec_init_eeprom ( netdev );
        !           203: 
        !           204:        /* read MAC address */
        !           205:        nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MAC_0, netdev->hw_addr,
        !           206:                   ETH_ALEN );
        !           207:        /* read mdio_register */
        !           208:        nvs_read ( &priv->eeprom.nvs, EEPROM_ADDR_MDIO_REGISTER,
        !           209:                   &priv->mdio_register, 2 );
        !           210: 
        !           211:        if ( ( rc = register_netdev ( netdev ) ) != 0 )
        !           212:                goto error;
        !           213: 
        !           214:        netdev_link_up ( netdev );
        !           215: 
        !           216:        DBGP ( "ints\n" );
        !           217: 
        !           218:        return 0;
        !           219: 
        !           220: error:
        !           221:        ifec_reset     ( netdev );
        !           222:        netdev_nullify ( netdev );
        !           223:        netdev_put     ( netdev );
        !           224: 
        !           225:        return rc;
        !           226: }
        !           227: 
        !           228: /*
        !           229:  * Remove a device from the PCI device list.
        !           230:  *
        !           231:  * @v pci              PCI device to remove.
        !           232:  *
        !           233:  * This is a PCI Device Driver API function.
        !           234:  */
        !           235: static void ifec_pci_remove ( struct pci_device *pci )
        !           236: {
        !           237:        struct net_device *netdev = pci_get_drvdata ( pci );
        !           238: 
        !           239:        DBGP ( "ifec_pci_remove\n" );
        !           240: 
        !           241:        unregister_netdev ( netdev );
        !           242:        ifec_reset        ( netdev );
        !           243:        netdev_nullify    ( netdev );
        !           244:        netdev_put        ( netdev );
        !           245: }
        !           246: 
        !           247: /****************** iPXE Network Device Driver API functions *****************/
        !           248: 
        !           249: /*
        !           250:  * Close a network device.
        !           251:  *
        !           252:  * @v netdev           Device to close.
        !           253:  *
        !           254:  * This is a iPXE Network Device Driver API function.
        !           255:  */
        !           256: static void ifec_net_close ( struct net_device *netdev )
        !           257: {
        !           258:        struct ifec_private *priv = netdev->priv;
        !           259:        unsigned long ioaddr = priv->ioaddr;
        !           260:        unsigned short intr_status;
        !           261: 
        !           262:        DBGP ( "ifec_net_close\n" );
        !           263: 
        !           264:        /* disable interrupts */
        !           265:        ifec_net_irq ( netdev, 0 );
        !           266: 
        !           267:        /* Ack & clear ints */
        !           268:        intr_status = inw ( ioaddr + SCBStatus );
        !           269:        outw ( intr_status, ioaddr + SCBStatus );
        !           270:        inw ( ioaddr + SCBStatus );
        !           271: 
        !           272:        ifec_reset ( netdev );
        !           273: 
        !           274:        /* Free any resources */
        !           275:        ifec_free ( netdev );
        !           276: }
        !           277: 
        !           278: /* Interrupts to be masked */
        !           279: #define INTERRUPT_MASK ( SCBMaskEarlyRx | SCBMaskFlowCtl )
        !           280: 
        !           281: /*
        !           282:  * Enable or disable IRQ masking.
        !           283:  *
        !           284:  * @v netdev           Device to control.
        !           285:  * @v enable           Zero to mask off IRQ, non-zero to enable IRQ.
        !           286:  *
        !           287:  * This is a iPXE Network Driver API function.
        !           288:  */
        !           289: static void ifec_net_irq ( struct net_device *netdev, int enable )
        !           290: {
        !           291:        struct ifec_private *priv = netdev->priv;
        !           292:        unsigned long ioaddr = priv->ioaddr;
        !           293: 
        !           294:        DBGP ( "ifec_net_irq\n" );
        !           295: 
        !           296:        outw ( enable ? INTERRUPT_MASK : SCBMaskAll, ioaddr + SCBCmd );
        !           297: }
        !           298: 
        !           299: /*
        !           300:  * Opens a network device.
        !           301:  *
        !           302:  * @v netdev           Device to be opened.
        !           303:  * @ret rc             Non-zero if failed to open.
        !           304:  *
        !           305:  * This enables tx and rx on the device.
        !           306:  * This is a iPXE Network Device Driver API function.
        !           307:  */
        !           308: static int ifec_net_open ( struct net_device *netdev )
        !           309: {
        !           310:        struct ifec_private *priv = netdev->priv;
        !           311:        struct ifec_ias *ias = NULL;
        !           312:        struct ifec_cfg *cfg = NULL;
        !           313:        int i, options;
        !           314:        int rc = -ENOMEM;
        !           315: 
        !           316:        DBGP ( "ifec_net_open: " );
        !           317: 
        !           318:        /* Ensure interrupts are disabled. */
        !           319:        ifec_net_irq ( netdev, 0 );
        !           320: 
        !           321:        /* Initialize Command Unit and Receive Unit base addresses. */
        !           322:        ifec_scb_cmd ( netdev, 0, RUAddrLoad );
        !           323:        ifec_scb_cmd ( netdev, virt_to_bus ( &priv->stats ), CUStatsAddr );
        !           324:        ifec_scb_cmd ( netdev, 0, CUCmdBase );
        !           325: 
        !           326:        /* Initialize both rings */
        !           327:        if ( ( rc = ifec_rx_setup ( netdev ) ) != 0 )
        !           328:                goto error;
        !           329:        if ( ( rc = ifec_tx_setup ( netdev ) ) != 0 )
        !           330:                goto error;
        !           331: 
        !           332:        /* Initialize MDIO */
        !           333:        options = 0x00; /* 0x40 = 10mbps half duplex, 0x00 = Autosense */
        !           334:        ifec_mdio_setup ( netdev, options );
        !           335: 
        !           336:        /* Prepare MAC address w/ Individual Address Setup (ias) command.*/
        !           337:        ias = malloc_dma ( sizeof ( *ias ), CB_ALIGN );
        !           338:        if ( !ias ) {
        !           339:                rc = -ENOMEM;
        !           340:                goto error;
        !           341:        }
        !           342:        ias->command      = CmdIASetup;
        !           343:        ias->status       = 0;
        !           344:        memcpy ( ias->ia, netdev->ll_addr, ETH_ALEN );
        !           345: 
        !           346:        /* Prepare operating parameters w/ a configure command. */
        !           347:        cfg = malloc_dma ( sizeof ( *cfg ), CB_ALIGN );
        !           348:        if ( !cfg ) {
        !           349:                rc = -ENOMEM;
        !           350:                goto error;
        !           351:        }
        !           352:        memcpy ( cfg, &ifec_cfg, sizeof ( *cfg ) );
        !           353:        cfg->link     = virt_to_bus ( priv->tcbs );
        !           354:        cfg->byte[19] = ( options & 0x10 ) ? 0xC0 : 0x80;
        !           355:        ias->link     = virt_to_bus ( cfg );
        !           356: 
        !           357:        /* Issue the ias and configure commands. */
        !           358:        ifec_scb_cmd ( netdev, virt_to_bus ( ias ), CUStart );
        !           359:        ifec_scb_cmd_wait ( netdev );
        !           360:        priv->configured = 1;
        !           361: 
        !           362:        /* Wait up to 10 ms for configuration to initiate */
        !           363:        for ( i = 10; i && !cfg->status; i-- )
        !           364:                mdelay ( 1 );
        !           365:        if ( ! cfg->status ) {
        !           366:                DBG ( "Failed to initiate!\n" );
        !           367:                goto error;
        !           368:        }
        !           369:        free_dma ( ias, sizeof ( *ias ) );
        !           370:        free_dma ( cfg, sizeof ( *cfg ) );
        !           371:        DBG2 ( "cfg " );
        !           372: 
        !           373:        /* Enable rx by sending ring address to card */
        !           374:        if ( priv->rfds[0] != NULL ) {
        !           375:                ifec_scb_cmd ( netdev, virt_to_bus( priv->rfds[0] ), RUStart );
        !           376:                ifec_scb_cmd_wait ( netdev );
        !           377:        }
        !           378:        DBG2 ( "rx_start\n" );
        !           379: 
        !           380:        return 0;
        !           381: 
        !           382: error:
        !           383:        free_dma ( cfg, sizeof ( *cfg ) );
        !           384:        free_dma ( ias, sizeof ( *ias ) );
        !           385:        ifec_free ( netdev );
        !           386:        ifec_reset ( netdev );
        !           387:        return rc;
        !           388: }
        !           389: 
        !           390: /*
        !           391:  * This function allows a driver to process events during operation.
        !           392:  *
        !           393:  * @v netdev           Device being polled.
        !           394:  *
        !           395:  * This is called periodically by iPXE to let the driver check the status of
        !           396:  * transmitted packets and to allow the driver to check for received packets.
        !           397:  * This is a iPXE Network Device Driver API function.
        !           398:  */
        !           399: static void ifec_net_poll ( struct net_device *netdev )
        !           400: {
        !           401:        struct ifec_private *priv = netdev->priv;
        !           402:        unsigned short intr_status;
        !           403: 
        !           404:        DBGP ( "ifec_net_poll\n" );
        !           405: 
        !           406:        /* acknowledge interrupts ASAP */
        !           407:        intr_status = inw ( priv->ioaddr + SCBStatus );
        !           408:        outw ( intr_status, priv->ioaddr + SCBStatus );
        !           409:        inw ( priv->ioaddr + SCBStatus );
        !           410: 
        !           411:        DBG2 ( "poll - status: 0x%04X\n", intr_status );
        !           412: 
        !           413:        /* anything to do here? */
        !           414:        if ( ( intr_status & ( ~INTERRUPT_MASK ) ) == 0 )
        !           415:                return;
        !           416: 
        !           417:        /* process received and transmitted packets */
        !           418:        ifec_tx_process ( netdev );
        !           419:        ifec_rx_process ( netdev );
        !           420: 
        !           421:        ifec_check_ru_status ( netdev, intr_status );
        !           422: 
        !           423:        return;
        !           424: }
        !           425: 
        !           426: /*
        !           427:  * This transmits a packet.
        !           428:  *
        !           429:  * @v netdev           Device to transmit from.
        !           430:  * @v iobuf            Data to transmit.
        !           431:  * @ret rc             Non-zero if failed to transmit.
        !           432:  *
        !           433:  * This is a iPXE Network Driver API function.
        !           434:  */
        !           435: static int ifec_net_transmit ( struct net_device *netdev,
        !           436:                                struct io_buffer *iobuf )
        !           437: {
        !           438:        struct ifec_private *priv = netdev->priv;
        !           439:        struct ifec_tcb *tcb = priv->tcb_head->next;
        !           440:        unsigned long ioaddr = priv->ioaddr;
        !           441: 
        !           442:        DBGP ( "ifec_net_transmit\n" );
        !           443: 
        !           444:        /* Wait for TCB to become available. */
        !           445:        if ( tcb->status || tcb->iob ) {
        !           446:                DBG ( "TX overflow\n" );
        !           447:                return -ENOBUFS;
        !           448:        }
        !           449: 
        !           450:        DBG2 ( "transmitting packet (%zd bytes). status = %hX, cmd=%hX\n",
        !           451:                iob_len ( iobuf ), tcb->status, inw ( ioaddr + SCBCmd ) );
        !           452: 
        !           453:        tcb->command   = CmdSuspend | CmdTx | CmdTxFlex;
        !           454:        tcb->count     = 0x01208000;
        !           455:        tcb->tbd_addr0 = virt_to_bus ( iobuf->data );
        !           456:        tcb->tbd_size0 = 0x3FFF & iob_len ( iobuf );
        !           457:        tcb->iob = iobuf;
        !           458: 
        !           459:        ifec_tx_wake ( netdev );
        !           460: 
        !           461:        /* Append to end of ring. */
        !           462:        priv->tcb_head = tcb;
        !           463: 
        !           464:        return 0;
        !           465: }
        !           466: 
        !           467: /*************************** Local support functions *************************/
        !           468: 
        !           469: /* Define what each GPIO Pin does */
        !           470: static const uint16_t ifec_ee_bits[] = {
        !           471:        [SPI_BIT_SCLK]  = EE_SHIFT_CLK,
        !           472:        [SPI_BIT_MOSI]  = EE_DATA_WRITE,
        !           473:        [SPI_BIT_MISO]  = EE_DATA_READ,
        !           474:        [SPI_BIT_SS(0)] = EE_ENB,
        !           475: };
        !           476: 
        !           477: /*
        !           478:  * Read a single bit from the GPIO pins used for SPI.
        !           479:  * should be called by SPI bitbash functions only
        !           480:  *
        !           481:  * @v basher           Bitbash device
        !           482:  * @v bit_id           Line to be read
        !           483:  */
        !           484: static int ifec_spi_read_bit ( struct bit_basher *basher,
        !           485:                               unsigned int bit_id )
        !           486: {
        !           487:        struct ifec_private *priv =
        !           488:                container_of ( basher, struct ifec_private, spi.basher );
        !           489:        unsigned long ee_addr = priv->ioaddr + CSREeprom;
        !           490:        unsigned int ret = 0;
        !           491:        uint16_t mask;
        !           492: 
        !           493:        DBGP ( "ifec_spi_read_bit\n" );
        !           494: 
        !           495:        mask = ifec_ee_bits[bit_id];
        !           496:        ret = inw (ee_addr);
        !           497: 
        !           498:        return ( ret & mask ) ? 1 : 0;
        !           499: }
        !           500: 
        !           501: /*
        !           502:  * Write a single bit to the GPIO pins used for SPI.
        !           503:  * should be called by SPI bitbash functions only
        !           504:  *
        !           505:  * @v basher           Bitbash device
        !           506:  * @v bit_id           Line to write to
        !           507:  * @v data             Value to write
        !           508:  */
        !           509: static void ifec_spi_write_bit ( struct bit_basher *basher,
        !           510:                                 unsigned int bit_id,
        !           511:                                 unsigned long data )
        !           512: {
        !           513:        struct ifec_private *priv =
        !           514:                container_of ( basher, struct ifec_private, spi.basher );
        !           515:        unsigned long ee_addr = priv->ioaddr + CSREeprom;
        !           516:        short val;
        !           517:        uint16_t mask = ifec_ee_bits[bit_id];
        !           518: 
        !           519:        DBGP ( "ifec_spi_write_bit\n" );
        !           520: 
        !           521:        val = inw ( ee_addr );
        !           522:        val &= ~mask;
        !           523:        val |= data & mask;
        !           524: 
        !           525:        outw ( val, ee_addr );
        !           526: }
        !           527: 
        !           528: /* set function pointer to SPI read- and write-bit functions */
        !           529: static struct bit_basher_operations ifec_basher_ops = {
        !           530:        .read = ifec_spi_read_bit,
        !           531:        .write = ifec_spi_write_bit,
        !           532: };
        !           533: 
        !           534: /*
        !           535:  * Initialize the eeprom stuff
        !           536:  *
        !           537:  * @v netdev           Network device
        !           538:  */
        !           539: static void ifec_init_eeprom ( struct net_device *netdev )
        !           540: {
        !           541:        struct ifec_private *priv = netdev->priv;
        !           542: 
        !           543:        DBGP ( "ifec_init_eeprom\n" );
        !           544: 
        !           545:        priv->spi.basher.op = &ifec_basher_ops;
        !           546:        priv->spi.bus.mode = SPI_MODE_THREEWIRE;
        !           547:        init_spi_bit_basher ( &priv->spi );
        !           548: 
        !           549:        priv->eeprom.bus = &priv->spi.bus;
        !           550: 
        !           551:        /* init as 93c46(93c14 compatible) first, to set the command len,
        !           552:         * block size and word len. Needs to be set for address len detection.
        !           553:         */
        !           554:        init_at93c46 ( &priv->eeprom, 16 );
        !           555: 
        !           556:        /* detect address length, */
        !           557:        threewire_detect_address_len ( &priv->eeprom );
        !           558: 
        !           559:        /* address len == 8 means 93c66 instead of 93c46 */
        !           560:        if ( priv->eeprom.address_len == 8 )
        !           561:                init_at93c66 ( &priv->eeprom, 16 );
        !           562: }
        !           563: 
        !           564: /*
        !           565:  * Support function: ifec_mdio_read
        !           566:  *
        !           567:  * This probably reads a register in the "physical media interface chip".
        !           568:  * -- REW
        !           569:  */
        !           570: static int ifec_mdio_read ( struct net_device *netdev, int phy_id,
        !           571:                                                        int location )
        !           572: {
        !           573:        struct ifec_private *priv = netdev->priv;
        !           574:        unsigned long ioaddr = priv->ioaddr;
        !           575:        int val;
        !           576:        int boguscnt = 64*4;     /* <64 usec. to complete, typ 27 ticks */
        !           577: 
        !           578:        DBGP ( "ifec_mdio_read\n" );
        !           579: 
        !           580:        outl ( 0x08000000 | ( location << 16 ) | ( phy_id << 21 ),
        !           581:               ioaddr + CSRCtrlMDI );
        !           582:        do {
        !           583:                udelay ( 16 );
        !           584: 
        !           585:                val = inl ( ioaddr + CSRCtrlMDI );
        !           586: 
        !           587:                if ( --boguscnt < 0 ) {
        !           588:                        DBG ( " ifec_mdio_read() time out with val = %X.\n",
        !           589:                                 val );
        !           590:                        break;
        !           591:                }
        !           592:        } while (! ( val & 0x10000000 ) );
        !           593:        return val & 0xffff;
        !           594: }
        !           595: 
        !           596: /*
        !           597:  * Initializes MDIO.
        !           598:  *
        !           599:  * @v netdev           Network device
        !           600:  * @v options          MDIO options
        !           601:  */
        !           602: static void ifec_mdio_setup ( struct net_device *netdev, int options )
        !           603: {
        !           604:        struct ifec_private *priv = netdev->priv;
        !           605:        unsigned short mdio_register = priv->mdio_register;
        !           606: 
        !           607:        DBGP ( "ifec_mdio_setup\n" );
        !           608: 
        !           609:        if (   ( (mdio_register>>8) & 0x3f ) == DP83840
        !           610:            || ( (mdio_register>>8) & 0x3f ) == DP83840A ) {
        !           611:                int mdi_reg23 = ifec_mdio_read ( netdev, mdio_register
        !           612:                                                  & 0x1f, 23 ) | 0x0422;
        !           613:                if (CONGENB)
        !           614:                        mdi_reg23 |= 0x0100;
        !           615:                DBG2 ( "DP83840 specific setup, setting register 23 to "
        !           616:                                                         "%hX.\n", mdi_reg23 );
        !           617:                ifec_mdio_write ( netdev, mdio_register & 0x1f, 23, mdi_reg23 );
        !           618:        }
        !           619:        DBG2 ( "dp83840 " );
        !           620:        if ( options != 0 ) {
        !           621:                ifec_mdio_write ( netdev, mdio_register & 0x1f, 0,
        !           622:                                           ( (options & 0x20) ? 0x2000 : 0 ) |
        !           623:                                           ( (options & 0x10) ? 0x0100 : 0 ) );
        !           624:                DBG2 ( "set mdio_register. " );
        !           625:        }
        !           626: }
        !           627: 
        !           628: /*
        !           629:  * Support function: ifec_mdio_write
        !           630:  *
        !           631:  * This probably writes to the "physical media interface chip".
        !           632:  * -- REW
        !           633:  */
        !           634: static int ifec_mdio_write ( struct net_device *netdev,
        !           635:                              int phy_id, int location, int value )
        !           636: {
        !           637:        struct ifec_private *priv = netdev->priv;
        !           638:        unsigned long ioaddr = priv->ioaddr;
        !           639:        int val;
        !           640:        int boguscnt = 64*4;     /* <64 usec. to complete, typ 27 ticks */
        !           641: 
        !           642:        DBGP ( "ifec_mdio_write\n" );
        !           643: 
        !           644:        outl ( 0x04000000 | ( location << 16 ) | ( phy_id << 21 ) | value,
        !           645:               ioaddr + CSRCtrlMDI );
        !           646:        do {
        !           647:                udelay ( 16 );
        !           648: 
        !           649:                val = inl ( ioaddr + CSRCtrlMDI );
        !           650:                if ( --boguscnt < 0 ) {
        !           651:                        DBG ( " ifec_mdio_write() time out with val = %X.\n",
        !           652:                              val );
        !           653:                        break;
        !           654:                }
        !           655:        } while (! ( val & 0x10000000 ) );
        !           656:        return val & 0xffff;
        !           657: }
        !           658: 
        !           659: /*
        !           660:  * Resets the hardware.
        !           661:  *
        !           662:  * @v netdev           Network device
        !           663:  */
        !           664: static void ifec_reset ( struct net_device *netdev )
        !           665: {
        !           666:        struct ifec_private *priv = netdev->priv;
        !           667:        unsigned long ioaddr = priv->ioaddr;
        !           668: 
        !           669:        DBGP ( "ifec_reset\n" );
        !           670: 
        !           671:        /* do partial reset first */
        !           672:        outl ( PortPartialReset, ioaddr + CSRPort );
        !           673:        inw ( ioaddr + SCBStatus );
        !           674:        udelay ( 20 );
        !           675: 
        !           676:        /* full reset */
        !           677:        outl ( PortReset, ioaddr + CSRPort );
        !           678:        inw ( ioaddr + SCBStatus );
        !           679:        udelay ( 20 );
        !           680: 
        !           681:        /* disable interrupts again */
        !           682:        ifec_net_irq ( netdev, 0 );
        !           683: }
        !           684: 
        !           685: /*
        !           686:  * free()s the tx/rx rings.
        !           687:  *
        !           688:  * @v netdev           Network device
        !           689:  */
        !           690: static void ifec_free ( struct net_device *netdev )
        !           691: {
        !           692:        struct ifec_private *priv = netdev_priv ( netdev );
        !           693:        int i;
        !           694: 
        !           695:        DBGP ( "ifec_free\n" );
        !           696: 
        !           697:        /* free all allocated receive io_buffers */
        !           698:        for ( i = 0; i < RFD_COUNT; i++ ) {
        !           699:                free_iob ( priv->rx_iobs[i] );
        !           700:                priv->rx_iobs[i] = NULL;
        !           701:                priv->rfds[i] = NULL;
        !           702:        }
        !           703: 
        !           704:        /* free TX ring buffer */
        !           705:        free_dma ( priv->tcbs, TX_RING_BYTES );
        !           706: 
        !           707:        priv->tcbs = NULL;
        !           708: }
        !           709: 
        !           710: /*
        !           711:  * Initializes an RFD.
        !           712:  *
        !           713:  * @v rfd              RFD struct to initialize
        !           714:  * @v command          Command word
        !           715:  * @v link             Link value
        !           716:  */
        !           717: static void ifec_rfd_init ( struct ifec_rfd *rfd, s16 command, u32 link )
        !           718: {
        !           719:        DBGP ( "ifec_rfd_init\n" );
        !           720: 
        !           721:        rfd->status      = 0;
        !           722:        rfd->command     = command;
        !           723:        rfd->rx_buf_addr = 0xFFFFFFFF;
        !           724:        rfd->count       = 0;
        !           725:        rfd->size        = RFD_PACKET_LEN;
        !           726:        rfd->link        = link;
        !           727: }
        !           728: 
        !           729: /*
        !           730:  * Send address of new RFD to card
        !           731:  *
        !           732:  * @v netdev           Network device
        !           733:  */
        !           734: static void ifec_reprime_ru ( struct net_device *netdev )
        !           735: {
        !           736:        struct ifec_private *priv = netdev->priv;
        !           737:        int cur_rx = priv->cur_rx;
        !           738:        
        !           739:        DBGP ( "ifec_reprime_ru\n" );
        !           740:        
        !           741:        if ( priv->rfds[cur_rx] != NULL ) {
        !           742:                ifec_scb_cmd ( netdev, virt_to_bus ( priv->rfds[cur_rx] ),
        !           743:                               RUStart );
        !           744:                ifec_scb_cmd_wait ( netdev );
        !           745:        }
        !           746: }
        !           747: 
        !           748: /*
        !           749:  * Check if reprime of RU needed
        !           750:  *
        !           751:  * @v netdev           Network device
        !           752:  */
        !           753: static void ifec_check_ru_status ( struct net_device *netdev,
        !           754:                                   unsigned short intr_status )
        !           755: {
        !           756:        struct ifec_private *priv = netdev->priv;
        !           757: 
        !           758:        DBGP ( "ifec_check_ru_status\n" );
        !           759: 
        !           760:        /*
        !           761:        * The chip may have suspended reception for various reasons.
        !           762:        * Check for that, and re-prime it should this be the case.
        !           763:        */
        !           764:        switch ( ( intr_status >> 2 ) & 0xf ) {
        !           765:                case 0:  /* Idle */
        !           766:                case 4:  /* Ready */
        !           767:                        break;
        !           768:                case 1:  /* Suspended */
        !           769:                case 2:  /* No resources (RFDs) */
        !           770:                case 9:  /* Suspended with no more RBDs */
        !           771:                case 10: /* No resources due to no RBDs */
        !           772:                case 12: /* Ready with no RBDs */
        !           773:                        DBG ( "ifec_net_poll: RU reprimed.\n" );
        !           774:                        ifec_reprime_ru ( netdev );
        !           775:                        break;
        !           776:                default:
        !           777:                        /* reserved values */
        !           778:                        DBG ( "ifec_net_poll: RU state anomaly: %i\n",
        !           779:                              ( inw ( priv->ioaddr + SCBStatus ) >> 2 ) & 0xf );
        !           780:                        break;
        !           781:        }
        !           782: }
        !           783: 
        !           784: #define RFD_STATUS ( RFD_OK | RFDRxCol | RFDRxErr | RFDShort | \
        !           785:                     RFDDMAOverrun | RFDNoBufs | RFDCRCError )
        !           786: /*
        !           787:  * Looks for received packets in the rx ring, reports success or error to
        !           788:  * the core accordingly. Starts reallocation of rx ring.
        !           789:  *
        !           790:  * @v netdev           Network device
        !           791:  */
        !           792: static void ifec_rx_process ( struct net_device *netdev )
        !           793: {
        !           794:        struct ifec_private *priv   = netdev->priv;
        !           795:        int cur_rx = priv->cur_rx;
        !           796:        struct io_buffer *iob = priv->rx_iobs[cur_rx];
        !           797:        struct ifec_rfd *rfd = priv->rfds[cur_rx];
        !           798:        unsigned int rx_len;
        !           799:        s16 status;
        !           800: 
        !           801:        DBGP ( "ifec_rx_process\n" );
        !           802: 
        !           803:        /* Process any received packets */
        !           804:        while ( iob && rfd && ( status = rfd->status ) ) {
        !           805:                rx_len = rfd->count & RFDMaskCount;
        !           806: 
        !           807:                DBG2 ( "Got a packet: Len = %d, cur_rx = %d.\n", rx_len,
        !           808:                       cur_rx );
        !           809:                DBGIO_HD ( (void*)rfd->packet, 0x30 );
        !           810: 
        !           811:                if ( ( status & ( RFD_STATUS & ~RFDShort ) ) != RFD_OK ) {
        !           812:                        DBG ( "Corrupted packet received. "
        !           813:                              "Status = %#08hx\n", status );
        !           814:                        netdev_rx_err ( netdev, iob, -EINVAL );
        !           815:                } else {
        !           816:                        /* Hand off the packet to the network subsystem */
        !           817:                        iob_put ( iob, rx_len );
        !           818:                        DBG2 ( "Received packet: %p, len: %d\n", iob, rx_len );
        !           819:                        netdev_rx ( netdev, iob );
        !           820:                }
        !           821: 
        !           822:                /* make sure we don't reuse this RFD */
        !           823:                priv->rx_iobs[cur_rx] = NULL;
        !           824:                priv->rfds[cur_rx] = NULL;
        !           825: 
        !           826:                /* Next RFD */
        !           827:                priv->cur_rx = ( cur_rx + 1 ) % RFD_COUNT;
        !           828:                cur_rx = priv->cur_rx;
        !           829:                iob = priv->rx_iobs[cur_rx];
        !           830:                rfd = priv->rfds[cur_rx];
        !           831:        }
        !           832: 
        !           833:        ifec_refill_rx_ring ( netdev );
        !           834: }
        !           835: 
        !           836: /*
        !           837:  * Allocates io_buffer, set pointers in ifec_private structure accordingly,
        !           838:  * reserves space for RFD header in io_buffer.
        !           839:  *
        !           840:  * @v netdev           Network device
        !           841:  * @v cur              Descriptor number to work on
        !           842:  * @v cmd              Value to set cmd field in RFD to
        !           843:  * @v link             Pointer to ned RFD
        !           844:  * @ret rc             0 on success, negative on failure
        !           845:  */
        !           846: static int ifec_get_rx_desc ( struct net_device *netdev, int cur, int cmd,
        !           847:                              int link )
        !           848: {
        !           849:        struct ifec_private *priv = netdev->priv;
        !           850:        struct ifec_rfd *rfd  = priv->rfds[cur];
        !           851: 
        !           852:        DBGP ( "ifec_get_rx_desc\n" );
        !           853: 
        !           854:        priv->rx_iobs[cur] = alloc_iob ( sizeof ( *rfd ) );
        !           855:        if ( ! priv->rx_iobs[cur] ) {
        !           856:                DBG ( "alloc_iob failed. desc. nr: %d\n", cur );
        !           857:                priv->rfds[cur] = NULL;
        !           858:                return -ENOMEM;
        !           859:        }
        !           860: 
        !           861:        /* Initialize new tail. */
        !           862:        priv->rfds[cur] = priv->rx_iobs[cur]->data;
        !           863:        ifec_rfd_init ( priv->rfds[cur], cmd, link );
        !           864:        iob_reserve ( priv->rx_iobs[cur], RFD_HEADER_LEN );
        !           865: 
        !           866:        return 0;
        !           867: }
        !           868: 
        !           869: /*
        !           870:  * Allocate new descriptor entries and initialize them if needed
        !           871:  *
        !           872:  * @v netdev           Network device
        !           873:  */
        !           874: static void ifec_refill_rx_ring ( struct net_device *netdev )
        !           875: {
        !           876:        struct ifec_private *priv = netdev->priv;
        !           877:        int i, cur_rx;
        !           878:        unsigned short intr_status;
        !           879: 
        !           880:        DBGP ( "ifec_refill_rx_ring\n" );
        !           881: 
        !           882:        for ( i = 0; i < RFD_COUNT; i++ ) {
        !           883:                cur_rx = ( priv->cur_rx + i ) % RFD_COUNT;
        !           884:                /* only refill if empty */
        !           885:                if ( priv->rfds[cur_rx] != NULL ||
        !           886:                     priv->rx_iobs[cur_rx] != NULL )
        !           887:                        continue;
        !           888: 
        !           889:                DBG2 ( "refilling RFD %d\n", cur_rx );
        !           890: 
        !           891:                if ( ifec_get_rx_desc ( netdev, cur_rx,
        !           892:                     CmdSuspend | CmdEndOfList, 0 ) == 0 ) {
        !           893:                        if ( i > 0 ) {
        !           894:                                int prev_rx = ( ( ( cur_rx + RFD_COUNT ) - 1 )
        !           895:                                                % RFD_COUNT );
        !           896:                                struct ifec_rfd *rfd = priv->rfds[prev_rx];
        !           897: 
        !           898:                                rfd->command = 0;
        !           899:                                rfd->link = virt_to_bus ( priv->rfds[cur_rx] );
        !           900:                        }
        !           901:                }
        !           902:        }
        !           903: 
        !           904:        intr_status = inw ( priv->ioaddr + SCBStatus );
        !           905:        ifec_check_ru_status ( netdev, intr_status );
        !           906: }
        !           907: 
        !           908: /*
        !           909:  * Initial allocation & initialization of the rx ring.
        !           910:  *
        !           911:  * @v netdev           Device of rx ring.
        !           912:  * @ret rc             Non-zero if error occured
        !           913:  */
        !           914: static int ifec_rx_setup ( struct net_device *netdev )
        !           915: {
        !           916:        struct ifec_private *priv = netdev->priv;
        !           917:        int i;
        !           918: 
        !           919:        DBGP ( "ifec_rx_setup\n" );
        !           920: 
        !           921:        priv->cur_rx = 0;
        !           922: 
        !           923:        /* init values for ifec_refill_rx_ring() */
        !           924:        for ( i = 0; i < RFD_COUNT; i++ ) {
        !           925:                priv->rfds[i] = NULL;
        !           926:                priv->rx_iobs[i] = NULL;
        !           927:        }
        !           928:        ifec_refill_rx_ring ( netdev );
        !           929: 
        !           930:        return 0;
        !           931: }
        !           932: 
        !           933: /*
        !           934:  * Initiates a SCB command.
        !           935:  *
        !           936:  * @v netdev           Network device
        !           937:  * @v ptr              General pointer value for command.
        !           938:  * @v cmd              Command to issue.
        !           939:  * @ret rc             Non-zero if command not issued.
        !           940:  */
        !           941: static int ifec_scb_cmd ( struct net_device *netdev, u32 ptr, u8 cmd )
        !           942: {
        !           943:        struct ifec_private *priv = netdev->priv;
        !           944:        unsigned long ioaddr = priv->ioaddr;
        !           945:        int rc;
        !           946: 
        !           947:        DBGP ( "ifec_scb_cmd\n" );
        !           948: 
        !           949:        rc = ifec_scb_cmd_wait ( netdev );      /* Wait until ready */
        !           950:        if ( !rc ) {
        !           951:                outl ( ptr, ioaddr + SCBPointer );
        !           952:                outb ( cmd, ioaddr + SCBCmd );          /* Issue command */
        !           953:        }
        !           954:        return rc;
        !           955: }
        !           956: 
        !           957: /*
        !           958:  * Wait for command unit to accept a command.
        !           959:  *
        !           960:  * @v cmd_ioaddr       I/O address of command register.
        !           961:  * @ret rc             Non-zero if command timed out.
        !           962:  */
        !           963: static int ifec_scb_cmd_wait ( struct net_device *netdev )
        !           964: {
        !           965:        struct ifec_private *priv = netdev->priv;
        !           966:        unsigned long cmd_ioaddr = priv->ioaddr + SCBCmd;
        !           967:        int rc, wait = CU_CMD_TIMEOUT;
        !           968: 
        !           969:        DBGP ( "ifec_scb_cmd_wait\n" );
        !           970: 
        !           971:        for ( ; wait && ( rc = inb ( cmd_ioaddr ) ); wait-- )
        !           972:                udelay ( 1 );
        !           973: 
        !           974:        if ( !wait )
        !           975:                DBG ( "ifec_scb_cmd_wait timeout!\n" );
        !           976:        return rc;
        !           977: }
        !           978: 
        !           979: /*
        !           980:  * Check status of transmitted packets & perform tx completions.
        !           981:  *
        !           982:  * @v netdev           Network device.
        !           983:  */
        !           984: static void ifec_tx_process ( struct net_device *netdev )
        !           985: {
        !           986:        struct ifec_private *priv = netdev->priv;
        !           987:        struct ifec_tcb *tcb = priv->tcb_tail;
        !           988:        s16 status;
        !           989: 
        !           990:        DBGP ( "ifec_tx_process\n" );
        !           991: 
        !           992:        /* Check status of transmitted packets */
        !           993:        while ( ( status = tcb->status ) && tcb->iob ) {
        !           994:                if ( status & TCB_U ) {
        !           995:                        /* report error to iPXE */
        !           996:                        DBG ( "ifec_tx_process : tx error!\n " );
        !           997:                        netdev_tx_complete_err ( netdev, tcb->iob, -EINVAL );
        !           998:                } else {
        !           999:                        /* report successful transmit */
        !          1000:                        netdev_tx_complete ( netdev, tcb->iob );
        !          1001:                }
        !          1002:                DBG2 ( "tx completion\n" );
        !          1003: 
        !          1004:                tcb->iob = NULL;
        !          1005:                tcb->status = 0;
        !          1006: 
        !          1007:                priv->tcb_tail = tcb->next;     /* Next TCB */
        !          1008:                tcb = tcb->next;
        !          1009:        }
        !          1010: }
        !          1011: 
        !          1012: /*
        !          1013:  * Allocates & initialize tx resources.
        !          1014:  *
        !          1015:  * @v netdev           Network device.
        !          1016:  * @ret rc             Non-zero if error occurred.
        !          1017:  */
        !          1018: static int ifec_tx_setup ( struct net_device *netdev )
        !          1019: {
        !          1020:        struct ifec_private *priv = netdev->priv;
        !          1021:        struct ifec_tcb *tcb;
        !          1022:        int i;
        !          1023: 
        !          1024:        DBGP ( "ifec_tx_setup\n" );
        !          1025: 
        !          1026:        /* allocate tx ring */
        !          1027:        priv->tcbs = malloc_dma ( TX_RING_BYTES, CB_ALIGN );
        !          1028:        if ( !priv->tcbs ) {
        !          1029:                DBG ( "TX-ring allocation failed\n" );
        !          1030:                return -ENOMEM;
        !          1031:        }
        !          1032: 
        !          1033:        tcb = priv->tcb_tail = priv->tcbs;
        !          1034:        priv->tx_curr = priv->tx_tail = 0;
        !          1035:        priv->tx_cnt = 0;
        !          1036: 
        !          1037:        for ( i = 0; i < TCB_COUNT; i++, tcb++ ) {
        !          1038:                tcb->status    = 0;
        !          1039:                tcb->count     = 0x01208000;
        !          1040:                tcb->iob       = NULL;
        !          1041:                tcb->tbda_addr = virt_to_bus ( &tcb->tbd_addr0 );
        !          1042:                tcb->link      = virt_to_bus ( tcb + 1 );
        !          1043:                tcb->next      = tcb + 1;
        !          1044:        }
        !          1045:        /* We point tcb_head at the last TCB, so the first ifec_net_transmit()
        !          1046:         * will use the first (head->next) TCB to transmit. */
        !          1047:        priv->tcb_head = --tcb;
        !          1048:        tcb->link = virt_to_bus ( priv->tcbs );
        !          1049:        tcb->next = priv->tcbs;
        !          1050:        
        !          1051:        return 0;
        !          1052: }
        !          1053: 
        !          1054: /*
        !          1055:  * Wake up the Command Unit and issue a Resume/Start.
        !          1056:  *
        !          1057:  * @v netdev           Network device containing Command Unit
        !          1058:  *
        !          1059:  * The time between clearing the S bit and issuing Resume must be as short as
        !          1060:  * possible to prevent a race condition. As noted in linux eepro100.c :
        !          1061:  *   Note: Watch out for the potential race condition here: imagine
        !          1062:  *     erasing the previous suspend
        !          1063:  *             the chip processes the previous command
        !          1064:  *             the chip processes the final command, and suspends
        !          1065:  *     doing the CU_RESUME
        !          1066:  *             the chip processes the next-yet-valid post-final-command.
        !          1067:  *   So blindly sending a CU_RESUME is only safe if we do it immediately after
        !          1068:  *   erasing the previous CmdSuspend, without the possibility of an intervening
        !          1069:  *   delay.
        !          1070:  */
        !          1071: void ifec_tx_wake ( struct net_device *netdev )
        !          1072: {
        !          1073:        struct ifec_private *priv = netdev->priv;
        !          1074:        unsigned long ioaddr = priv->ioaddr;
        !          1075:        struct ifec_tcb *tcb = priv->tcb_head->next;
        !          1076: 
        !          1077:        DBGP ( "ifec_tx_wake\n" );
        !          1078: 
        !          1079:        /* For the special case of the first transmit, we issue a START. The
        !          1080:         * card won't RESUME after the configure command. */
        !          1081:        if ( priv->configured ) {
        !          1082:                priv->configured = 0;
        !          1083:                ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
        !          1084:                ifec_scb_cmd_wait ( netdev );
        !          1085:                return;
        !          1086:        }
        !          1087: 
        !          1088:        /* Resume if suspended. */
        !          1089:        switch ( ( inw ( ioaddr + SCBStatus ) >> 6 ) & 0x3 ) {
        !          1090:        case 0:  /* Idle - We should not reach this state. */
        !          1091:                DBG2 ( "ifec_tx_wake: tx idle!\n" );
        !          1092:                ifec_scb_cmd ( netdev, virt_to_bus ( tcb ), CUStart );
        !          1093:                ifec_scb_cmd_wait ( netdev );
        !          1094:                return;
        !          1095:        case 1:  /* Suspended */
        !          1096:                DBG2 ( "s" );
        !          1097:                break;
        !          1098:        default: /* Active */
        !          1099:                DBG2 ( "a" );
        !          1100:        }
        !          1101:        ifec_scb_cmd_wait ( netdev );
        !          1102:        outl ( 0, ioaddr + SCBPointer );
        !          1103:        priv->tcb_head->command &= ~CmdSuspend;
        !          1104:        /* Immediately issue Resume command */
        !          1105:        outb ( CUResume, ioaddr + SCBCmd );
        !          1106:        ifec_scb_cmd_wait ( netdev );
        !          1107: }
        !          1108: 
        !          1109: /*********************************************************************/
        !          1110: 
        !          1111: static struct pci_device_id ifec_nics[] = {
        !          1112: PCI_ROM(0x8086, 0x1029, "id1029",        "Intel EtherExpressPro100 ID1029", 0),
        !          1113: PCI_ROM(0x8086, 0x1030, "id1030",        "Intel EtherExpressPro100 ID1030", 0),
        !          1114: PCI_ROM(0x8086, 0x1031, "82801cam",      "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
        !          1115: PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection", 0),
        !          1116: PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection", 0),
        !          1117: PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection", 0),
        !          1118: PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
        !          1119: PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
        !          1120: PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller", 0),
        !          1121: PCI_ROM(0x8086, 0x1038, "id1038",        "Intel PRO/100 VM Network Connection", 0),
        !          1122: PCI_ROM(0x8086, 0x1039, "82562et",       "Intel PRO100 VE 82562ET", 0),
        !          1123: PCI_ROM(0x8086, 0x103a, "id103a",        "Intel Corporation 82559 InBusiness 10/100", 0),
        !          1124: PCI_ROM(0x8086, 0x103b, "82562etb",      "Intel PRO100 VE 82562ETB", 0),
        !          1125: PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection", 0),
        !          1126: PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection", 0),
        !          1127: PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection", 0),
        !          1128: PCI_ROM(0x8086, 0x1051, "prove",         "Intel PRO/100 VE Network Connection", 0),
        !          1129: PCI_ROM(0x8086, 0x1059, "82551qm",       "Intel PRO/100 M Mobile Connection", 0),
        !          1130: PCI_ROM(0x8086, 0x1209, "82559er",       "Intel EtherExpressPro100 82559ER", 0),
        !          1131: PCI_ROM(0x8086, 0x1227, "82865",         "Intel 82865 EtherExpress PRO/100A", 0),
        !          1132: PCI_ROM(0x8086, 0x1228, "82556",         "Intel 82556 EtherExpress PRO/100 Smart", 0),
        !          1133: PCI_ROM(0x8086, 0x1229, "eepro100",      "Intel EtherExpressPro100", 0),
        !          1134: PCI_ROM(0x8086, 0x2449, "82562em",       "Intel EtherExpressPro100 82562EM", 0),
        !          1135: PCI_ROM(0x8086, 0x2459, "82562-1",       "Intel 82562 based Fast Ethernet Connection", 0),
        !          1136: PCI_ROM(0x8086, 0x245d, "82562-2",       "Intel 82562 based Fast Ethernet Connection", 0),
        !          1137: PCI_ROM(0x8086, 0x1050, "82562ez",       "Intel 82562EZ Network Connection", 0),
        !          1138: PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller", 0),
        !          1139: PCI_ROM(0x8086, 0x1065, "82562-3",       "Intel 82562 based Fast Ethernet Connection", 0),
        !          1140: PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server", 0),
        !          1141: PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server", 0),
        !          1142: PCI_ROM(0x8086, 0x1092, "82562-3",       "Intel Pro/100 VE Network", 0),
        !          1143: PCI_ROM(0x8086, 0x27dc, "eepro100-27dc", "Intel 82801G (ICH7) Chipset Ethernet Controller", 0),
        !          1144: };
        !          1145: 
        !          1146: /* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need
        !          1147:  * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c)
        !          1148:  * 2003/03/17 gbaum */
        !          1149: 
        !          1150: struct pci_driver ifec_driver __pci_driver = {
        !          1151:        .ids      = ifec_nics,
        !          1152:        .id_count = ( sizeof (ifec_nics) / sizeof (ifec_nics[0]) ),
        !          1153:        .probe    = ifec_pci_probe,
        !          1154:        .remove   = ifec_pci_remove
        !          1155: };
        !          1156: 
        !          1157: /*
        !          1158:  * Local variables:
        !          1159:  *  c-basic-offset: 8
        !          1160:  *  c-indent-level: 8
        !          1161:  *  tab-width: 8
        !          1162:  * End:
        !          1163:  */

unix.superglobalmegacorp.com

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