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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2010 Andrei Faur <[email protected]>
        !             3:  *
        !             4:  * This program is free software; you can redistribute it and/or
        !             5:  * modify it under the terms of the GNU General Public License as
        !             6:  * published by the Free Software Foundation; either version 2 of the
        !             7:  * License, or any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful, but
        !            10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12:  * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  *
        !            18:  */
        !            19: 
        !            20: FILE_LICENCE ( GPL2_OR_LATER );
        !            21: 
        !            22: #include <stdint.h>
        !            23: #include <stdio.h>
        !            24: #include <stdlib.h>
        !            25: #include <string.h>
        !            26: #include <unistd.h>
        !            27: #include <assert.h>
        !            28: #include <byteswap.h>
        !            29: #include <errno.h>
        !            30: #include <ipxe/ethernet.h>
        !            31: #include <ipxe/if_ether.h>
        !            32: #include <ipxe/io.h>
        !            33: #include <ipxe/iobuf.h>
        !            34: #include <ipxe/malloc.h>
        !            35: #include <ipxe/netdevice.h>
        !            36: #include <ipxe/pci.h>
        !            37: #include <ipxe/timer.h>
        !            38: #include <mii.h>
        !            39: #include "pcnet32.h"
        !            40: 
        !            41: static u16 pcnet32_wio_read_csr ( unsigned long addr, int index )
        !            42: {
        !            43:        outw ( index, addr + PCNET32_WIO_RAP );
        !            44:        return inw ( addr + PCNET32_WIO_RDP );
        !            45: }
        !            46: 
        !            47: static void pcnet32_wio_write_csr ( unsigned long addr, int index, u16 val )
        !            48: {
        !            49:        outw ( index, addr + PCNET32_WIO_RAP );
        !            50:        outw ( val, addr + PCNET32_WIO_RDP );
        !            51: }
        !            52: 
        !            53: static u16 pcnet32_wio_read_bcr ( unsigned long addr, int index )
        !            54: {
        !            55:        outw ( index, addr + PCNET32_WIO_RAP );
        !            56:        return inw ( addr + PCNET32_WIO_BDP );
        !            57: }
        !            58: 
        !            59: static void pcnet32_wio_write_bcr ( unsigned long addr, int index, u16 val )
        !            60: {
        !            61:        outw ( index, addr + PCNET32_WIO_RAP );
        !            62:        outw ( val, addr + PCNET32_WIO_BDP );
        !            63: }
        !            64: 
        !            65: static u16 pcnet32_wio_read_rap ( unsigned long addr )
        !            66: {
        !            67:        return inw ( addr + PCNET32_WIO_RAP );
        !            68: }
        !            69: 
        !            70: static void pcnet32_wio_write_rap ( unsigned long addr , u16 val )
        !            71: {
        !            72:        outw ( val, addr + PCNET32_WIO_RAP );
        !            73: }
        !            74: 
        !            75: static void pcnet32_wio_reset ( unsigned long addr )
        !            76: {
        !            77:        inw ( addr + PCNET32_WIO_RESET );
        !            78: }
        !            79: 
        !            80: static int pcnet32_wio_check ( unsigned long addr )
        !            81: {
        !            82:        outw ( 88, addr + PCNET32_WIO_RAP );
        !            83:        return ( inw ( addr + PCNET32_WIO_RAP ) == 88 );
        !            84: }
        !            85: 
        !            86: static struct pcnet32_access pcnet32_wio = {
        !            87:        .read_csr       = pcnet32_wio_read_csr,
        !            88:        .write_csr      = pcnet32_wio_write_csr,
        !            89:        .read_bcr       = pcnet32_wio_read_bcr,
        !            90:        .write_bcr      = pcnet32_wio_write_bcr,
        !            91:        .read_rap       = pcnet32_wio_read_rap,
        !            92:        .write_rap      = pcnet32_wio_write_rap,
        !            93:        .reset          = pcnet32_wio_reset,
        !            94: };
        !            95: 
        !            96: static u16 pcnet32_dwio_read_csr ( unsigned long addr, int index )
        !            97: {
        !            98:        outl ( index, addr + PCNET32_DWIO_RAP );
        !            99:        return ( inl ( addr + PCNET32_DWIO_RDP ) & 0xffff );
        !           100: }
        !           101: 
        !           102: static void pcnet32_dwio_write_csr ( unsigned long addr, int index, u16 val )
        !           103: {
        !           104:        outl ( index, addr + PCNET32_DWIO_RAP );
        !           105:        outl ( val, addr + PCNET32_DWIO_RDP );
        !           106: }
        !           107: 
        !           108: static u16 pcnet32_dwio_read_bcr ( unsigned long addr, int index )
        !           109: {
        !           110:        outl ( index, addr + PCNET32_DWIO_RAP );
        !           111:        return ( inl ( addr + PCNET32_DWIO_BDP ) & 0xffff );
        !           112: }
        !           113: 
        !           114: static void pcnet32_dwio_write_bcr ( unsigned long addr, int index, u16 val )
        !           115: {
        !           116:        outl ( index, addr + PCNET32_DWIO_RAP );
        !           117:        outl ( val, addr + PCNET32_DWIO_BDP );
        !           118: }
        !           119: 
        !           120: static u16 pcnet32_dwio_read_rap ( unsigned long addr )
        !           121: {
        !           122:        return ( inl ( addr + PCNET32_DWIO_RAP ) & 0xffff );
        !           123: }
        !           124: 
        !           125: static void pcnet32_dwio_write_rap ( unsigned long addr , u16 val )
        !           126: {
        !           127:        outl ( val, addr + PCNET32_DWIO_RAP );
        !           128: }
        !           129: 
        !           130: static void pcnet32_dwio_reset ( unsigned long addr )
        !           131: {
        !           132:        inl ( addr + PCNET32_DWIO_RESET );
        !           133: }
        !           134: 
        !           135: static int pcnet32_dwio_check ( unsigned long addr )
        !           136: {
        !           137:        outl ( 88, addr + PCNET32_DWIO_RAP );
        !           138:        return ( ( inl ( addr + PCNET32_DWIO_RAP ) & 0xffff ) == 88 );
        !           139: }
        !           140: 
        !           141: 
        !           142: static struct pcnet32_access pcnet32_dwio = {
        !           143:        .read_csr       = pcnet32_dwio_read_csr,
        !           144:        .write_csr      = pcnet32_dwio_write_csr,
        !           145:        .read_bcr       = pcnet32_dwio_read_bcr,
        !           146:        .write_bcr      = pcnet32_dwio_write_bcr,
        !           147:        .read_rap       = pcnet32_dwio_read_rap,
        !           148:        .write_rap      = pcnet32_dwio_write_rap,
        !           149:        .reset          = pcnet32_dwio_reset,
        !           150: };
        !           151: 
        !           152: static int
        !           153: pcnet32_mdio_read ( struct net_device *netdev, int phy, int reg )
        !           154: {
        !           155:        struct pcnet32_private *priv = netdev->priv;
        !           156:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           157:        u16 val_out;
        !           158: 
        !           159:        if ( ! priv->mii )
        !           160:                return 0;
        !           161: 
        !           162:        /* First, select PHY chip and the register we want to read */
        !           163:        priv->a->write_bcr ( ioaddr, 33,
        !           164:                ( ( phy & 0x1f ) << 5 ) | ( reg & 0x1f ) );
        !           165: 
        !           166:        /* Read the selected register's value */
        !           167:        val_out = priv->a->read_bcr ( ioaddr, 34 );
        !           168: 
        !           169:        return val_out;
        !           170: }
        !           171: 
        !           172: static void
        !           173: __unused pcnet32_mdio_write ( struct net_device *netdev, int phy, int reg, int val )
        !           174: {
        !           175:        struct pcnet32_private *priv = netdev->priv;
        !           176:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           177: 
        !           178:        if ( ! priv->mii )
        !           179:                return;
        !           180: 
        !           181:        /* First, select PHY chip and the register we want to write to */
        !           182:        priv->a->write_bcr ( ioaddr, 33,
        !           183:                ( ( phy & 0x1f ) << 5 ) | ( reg & 0x1f ) );
        !           184: 
        !           185:        /* Write val to the selected register */
        !           186:        priv->a->write_bcr ( ioaddr, 34, val );
        !           187: }
        !           188: 
        !           189: 
        !           190: /**
        !           191:  * pcnet32_refill_rx_ring - Allocates iobufs for every Rx descriptor
        !           192:  * that doesn't have one and isn't in use by the hardware
        !           193:  *
        !           194:  * @v priv     Driver private structure
        !           195:  */
        !           196: static void
        !           197: pcnet32_refill_rx_ring ( struct pcnet32_private *priv )
        !           198: {
        !           199:        struct pcnet32_rx_desc *rx_curr_desc;
        !           200:        u16 status;
        !           201:        int i;
        !           202: 
        !           203:        DBGP ( "pcnet32_refill_rx_ring\n" );
        !           204: 
        !           205:        for ( i = 0; i < RX_RING_SIZE; i++ ) {
        !           206:                rx_curr_desc = priv->rx_base + i;
        !           207: 
        !           208:                status = le16_to_cpu ( rx_curr_desc->status );
        !           209: 
        !           210:                /* Don't touch descriptors owned by the hardware */
        !           211:                if ( status & DescOwn )
        !           212:                        continue;
        !           213: 
        !           214:                /* Descriptors with iobufs still need to be processed */
        !           215:                if ( priv->rx_iobuf[i] != NULL )
        !           216:                        continue;
        !           217: 
        !           218:                /* If alloc_iob fails, try again later (next poll) */
        !           219:                if ( ! ( priv->rx_iobuf[i] = alloc_iob ( PKT_BUF_SIZE ) ) ) {
        !           220:                        DBG ( "Refill rx ring failed\n" );
        !           221:                        break;
        !           222:                }
        !           223: 
        !           224:                rx_curr_desc->base =
        !           225:                        cpu_to_le32 ( virt_to_bus ( priv->rx_iobuf[i]->data ) );
        !           226:                rx_curr_desc->buf_length = cpu_to_le16 ( -PKT_BUF_SIZE );
        !           227:                rx_curr_desc->msg_length = rx_curr_desc->reserved = 0;
        !           228: 
        !           229:                /* Owner changes after the other status fields are set */
        !           230:                wmb();
        !           231:                rx_curr_desc->status = cpu_to_le16 ( DescOwn );
        !           232:        }
        !           233: 
        !           234: }
        !           235: 
        !           236: /**
        !           237:  * pcnet32_setup_rx_resources - allocate Rx resources (Descriptors)
        !           238:  *
        !           239:  * @v priv     Driver private structure
        !           240:  *
        !           241:  * @ret rc     Returns 0 on success, negative on failure
        !           242:  */
        !           243: static int
        !           244: pcnet32_setup_rx_resources ( struct pcnet32_private *priv )
        !           245: {
        !           246:        DBGP ( "pcnet32_setup_rx_resources\n" );
        !           247: 
        !           248:        priv->rx_base = malloc_dma ( RX_RING_BYTES, RX_RING_ALIGN );
        !           249: 
        !           250:        DBG ( "priv->rx_base = %#08lx\n", virt_to_bus ( priv->rx_base ) );
        !           251: 
        !           252:        if ( ! priv->rx_base ) {
        !           253:                return -ENOMEM;
        !           254:        }
        !           255: 
        !           256:        memset ( priv->rx_base, 0, RX_RING_BYTES );
        !           257: 
        !           258:        pcnet32_refill_rx_ring ( priv );
        !           259: 
        !           260:        priv->rx_curr = 0;
        !           261: 
        !           262:        return 0;
        !           263: }
        !           264: 
        !           265: static void
        !           266: pcnet32_free_rx_resources ( struct pcnet32_private *priv )
        !           267: {
        !           268:        int i;
        !           269: 
        !           270:        DBGP ( "pcnet32_free_rx_resources\n" );
        !           271: 
        !           272:        free_dma ( priv->rx_base, RX_RING_BYTES );
        !           273: 
        !           274:        for ( i = 0; i < RX_RING_SIZE; i++ ) {
        !           275:                free_iob ( priv->rx_iobuf[i] );
        !           276:                priv->rx_iobuf[i] = NULL;
        !           277:        }
        !           278: }
        !           279: 
        !           280: /**
        !           281:  * pcnet32_setup_tx_resources - allocate Tx resources (Descriptors)
        !           282:  *
        !           283:  * @v priv     Driver private structure
        !           284:  *
        !           285:  * @ret rc     Returns 0 on success, negative on failure
        !           286:  */
        !           287: static int
        !           288: pcnet32_setup_tx_resources ( struct pcnet32_private *priv )
        !           289: {
        !           290:        DBGP ( "pcnet32_setup_tx_resources\n" );
        !           291: 
        !           292:        priv->tx_base = malloc_dma ( TX_RING_BYTES, TX_RING_ALIGN );
        !           293: 
        !           294:        if ( ! priv->tx_base ) {
        !           295:                return -ENOMEM;
        !           296:        }
        !           297: 
        !           298:        memset ( priv->tx_base, 0, TX_RING_BYTES );
        !           299: 
        !           300:        DBG ( "priv->tx_base = %#08lx\n", virt_to_bus ( priv->tx_base ) );
        !           301: 
        !           302:        priv->tx_curr = 0;
        !           303:        priv->tx_fill_ctr = 0;
        !           304:        priv->tx_tail = 0;
        !           305: 
        !           306:        return 0;
        !           307: }
        !           308: 
        !           309: static void
        !           310: pcnet32_free_tx_resources ( struct pcnet32_private *priv )
        !           311: {
        !           312:        DBGP ( "pcnet32_free_tx_resources\n" );
        !           313: 
        !           314:        free_dma ( priv->tx_base, TX_RING_BYTES );
        !           315: }
        !           316: 
        !           317: static int
        !           318: pcnet32_chip_detect ( struct pcnet32_private *priv )
        !           319: {
        !           320:        int fdx, mii, fset;
        !           321:        int media;
        !           322:        int rc;
        !           323:        unsigned long ioaddr;
        !           324:        struct pcnet32_access *a;
        !           325:        int chip_version;
        !           326:        char *chipname;
        !           327: 
        !           328:        ioaddr = priv->pci_dev->ioaddr;
        !           329:        a = priv->a;
        !           330: 
        !           331:        chip_version = a->read_csr ( ioaddr, 88 )
        !           332:                | ( a->read_csr ( ioaddr, 89 ) << 16 );
        !           333: 
        !           334:        rc = -ENODEV;
        !           335: 
        !           336:        DBG ( "PCnet chip version is 0x%X\n", chip_version );
        !           337:        if ( ( chip_version & 0xfff ) != 0x003 )
        !           338:                goto err_unsupported;
        !           339: 
        !           340:        fdx = mii = fset = 0;
        !           341:        chip_version = ( chip_version >> 12 ) & 0xffff;
        !           342: 
        !           343:        switch (chip_version) {
        !           344:        case 0x2420:
        !           345:                chipname = "PCnet/PCI 79C970";
        !           346:                break;
        !           347:        case 0x2430:
        !           348:                /* 970 gives the wrong chip id back */
        !           349:                chipname = "PCnet/PCI 79C970";
        !           350:                break;
        !           351:        case 0x2621:
        !           352:                chipname = "PCnet/PCI II 79C970A";
        !           353:                fdx = 1;
        !           354:                break;
        !           355:        case 0x2623:
        !           356:                chipname = "PCnet/FAST 79C971";
        !           357:                fdx = 1;
        !           358:                mii = 1;
        !           359:                fset = 1;
        !           360:                break;
        !           361:        case 0x2624:
        !           362:                chipname = "PCnet/FAST+ 79C972";
        !           363:                fdx = 1;
        !           364:                mii = 1;
        !           365:                fset = 1;
        !           366:                break;
        !           367:        case 0x2625:
        !           368:                chipname = "PCnet/FAST III 79C973";
        !           369:                fdx = 1;
        !           370:                mii = 1;
        !           371:                break;
        !           372:        case 0x2626:
        !           373:                chipname = "PCnet/Home 79C978";
        !           374:                fdx = 1;
        !           375:                /*
        !           376:                 * This is based on specs published at www.amd.com. This section
        !           377:                 * assumes that a NIC with a 79C978 wants to go into 1Mb HomePNA
        !           378:                 * mode. The 79C978 can also go into standard ethernet, and
        !           379:                 * there probably should be some sort of module option to select
        !           380:                 * the mode by which the card should operate
        !           381:                 */
        !           382:                /* switch to home wiring mode */
        !           383:                media = a->read_bcr(ioaddr, 49);
        !           384: 
        !           385:                DBG ( "media reset to %#x.\n", media );
        !           386:                a->write_bcr(ioaddr, 49, media);
        !           387:                break;
        !           388:        case 0x2627:
        !           389:                chipname = "PCnet/FAST III 79C975";
        !           390:                fdx = 1;
        !           391:                mii = 1;
        !           392:                break;
        !           393:        case 0x2628:
        !           394:                chipname = "PCnet/PRO 79C976";
        !           395:                fdx = 1;
        !           396:                mii = 1;
        !           397:                break;
        !           398:        default:
        !           399:                chipname = "UNKNOWN";
        !           400:                DBG ( "PCnet version %#x, no PCnet32 chip.\n", chip_version );
        !           401:                goto err_unsupported;
        !           402:        }
        !           403: 
        !           404:        DBG ( "PCnet chipname %s\n", chipname );
        !           405: 
        !           406:        /*
        !           407:         * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
        !           408:         * starting until the packet is loaded. Strike one for reliability, lose
        !           409:         * one for latency - although on PCI this isnt a big loss. Older chips
        !           410:         * have FIFO's smaller than a packet, so you can't do this.
        !           411:         * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn.
        !           412:         */
        !           413:        if (fset) {
        !           414:                a->write_bcr ( ioaddr, 18,
        !           415:                        ( a->read_bcr ( ioaddr, 18 ) | 0x0860 ) );
        !           416:                a->write_csr ( ioaddr, 80,
        !           417:                        ( a->read_csr ( ioaddr, 80 ) & 0x0C00) | 0x0C00 );
        !           418:        }
        !           419: 
        !           420:        priv->full_duplex = fdx;
        !           421:        priv->mii = mii;
        !           422: 
        !           423:        return 0;
        !           424: 
        !           425: err_unsupported:
        !           426:        return rc;
        !           427: }
        !           428: 
        !           429: /**
        !           430:  * pcnet32_set_ops - Determines the ops used to access the registers
        !           431:  *
        !           432:  * @v priv     Driver private structure
        !           433:  *
        !           434:  * @ret rc     Returns 0 on success, negative on failure
        !           435:  */
        !           436: static int
        !           437: pcnet32_set_ops ( struct pcnet32_private *priv )
        !           438: {
        !           439:        int rc;
        !           440:        unsigned long ioaddr;
        !           441: 
        !           442:        ioaddr = priv->pci_dev->ioaddr;
        !           443: 
        !           444:        /* Check if CSR0 has its default value and perform a write / read
        !           445:           in the RAP register to see if it works. Based on these results
        !           446:           determine what mode the NIC is in (WIO / DWIO)
        !           447:         */
        !           448:        rc = -ENODEV;
        !           449: 
        !           450:        if ( pcnet32_wio_read_csr ( ioaddr, 0 ) == 4 &&
        !           451:             pcnet32_wio_check ( ioaddr ) ) {
        !           452:                priv->a = &pcnet32_wio;
        !           453:        } else {
        !           454:                pcnet32_dwio_reset ( ioaddr );
        !           455:                if ( pcnet32_dwio_read_csr ( ioaddr, 0 ) == 4 &&
        !           456:                     pcnet32_dwio_check ( ioaddr ) ) {
        !           457:                        priv->a = &pcnet32_dwio;
        !           458:                } else {
        !           459:                        goto err_unsupported;
        !           460:                }
        !           461:        }
        !           462: 
        !           463:        return 0;
        !           464: 
        !           465: err_unsupported:
        !           466:        return rc;
        !           467: }
        !           468: 
        !           469: /**
        !           470:  * pcnet32_setup_init_block - setup the NICs initialization block
        !           471:  *
        !           472:  * @v priv     Driver private structure
        !           473:  *
        !           474:  * @ret rc     Returns 0 on success, negative on failure
        !           475:  */
        !           476: static void
        !           477: pcnet32_setup_init_block ( struct pcnet32_private *priv )
        !           478: {
        !           479:        int i;
        !           480: 
        !           481:        /* Configure the network port based on what we've established so far */
        !           482:        priv->init_block.mode =
        !           483:                cpu_to_le16 ( ( priv->options & PCNET32_PORT_PORTSEL ) << 7 );
        !           484: 
        !           485:        /* Setup RLEN and TLEN fields */
        !           486:        priv->init_block.tlen_rlen =
        !           487:                cpu_to_le16 ( ( PCNET32_LOG_RX_BUFFERS << 4 ) |
        !           488:                              ( PCNET32_LOG_TX_BUFFERS << 12 ) );
        !           489: 
        !           490:        /* Fill in physical address */
        !           491:        for ( i = 0; i < ETH_ALEN; i++)
        !           492:                priv->init_block.phys_addr[i] = priv->netdev->hw_addr[i];
        !           493: 
        !           494:        /* No multicasting scheme, accept everything */
        !           495:        priv->init_block.filter[0] = 0xffffffff;
        !           496:        priv->init_block.filter[1] = 0xffffffff;
        !           497: 
        !           498:        priv->init_block.rx_ring =
        !           499:                cpu_to_le32 ( virt_to_bus ( priv->rx_base ) );
        !           500:        priv->init_block.tx_ring =
        !           501:                cpu_to_le32 ( virt_to_bus ( priv->tx_base ) );
        !           502: 
        !           503:        /* Make sure all changes are visible */
        !           504:        wmb();
        !           505: }
        !           506: 
        !           507: /**
        !           508:  * pcnet32_setup_probe_phy - go through all PHYs and see which one is present
        !           509:  *
        !           510:  * @v priv     Driver private structure
        !           511:  */
        !           512: static void
        !           513: pcnet32_setup_probe_phy ( struct pcnet32_private *priv )
        !           514: {
        !           515:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           516:        unsigned int phycount = 0;
        !           517:        int phy_id;
        !           518:        int i;
        !           519: 
        !           520:        if ( priv->mii ) {
        !           521:                phy_id = ( ( priv->a->read_bcr ( ioaddr, 33 ) ) >> 5 ) & 0x1f;
        !           522:                for ( i = 0; i < PCNET32_MAX_PHYS; i++ ) {
        !           523:                        unsigned short id1, id2;
        !           524:                        id1 = pcnet32_mdio_read ( priv->netdev, i, MII_PHYSID1 );
        !           525:                        if ( id1 == 0xffff )
        !           526:                                continue;
        !           527:                        id2 = pcnet32_mdio_read ( priv->netdev, i, MII_PHYSID2 );
        !           528:                        if ( id2 == 0xffff )
        !           529:                                continue;
        !           530:                        if ( i == 31 && ( ( priv->chip_version + 1 ) & 0xfffe ) == 0x2624 )
        !           531:                                continue;
        !           532: 
        !           533:                        phycount++;
        !           534:                        phy_id = i;
        !           535:                }
        !           536:                priv->a->write_bcr ( ioaddr, 33, phy_id << 5 );
        !           537:                if ( phycount > 1 )
        !           538:                        priv->options |= PCNET32_PORT_MII;
        !           539:        }
        !           540: }
        !           541: 
        !           542: /**
        !           543:  * pcnet32_setup_mac_addr - check for inconsistency between CSR12-14
        !           544:  * and PROM addresses
        !           545:  *
        !           546:  * @v priv     Driver private structure
        !           547:  */
        !           548: static int
        !           549: pcnet32_setup_mac_addr ( struct pcnet32_private *priv )
        !           550: {
        !           551:        int i;
        !           552:        u8 promaddr[ETH_ALEN];
        !           553:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           554: 
        !           555:        /* In most chips, after a chip reset, the ethernet address is read from
        !           556:         * the station address PROM at the base address and programmed into the
        !           557:         * "Physical Address Registers" CSR12-14.
        !           558:         * As a precautionary measure, we read the PROM values and complain if
        !           559:         * they disagree with the CSRs.  If they miscompare, and the PROM addr
        !           560:         * is valid, then the PROM addr is used.
        !           561:         */
        !           562:        for ( i = 0; i < 3; i++ ) {
        !           563:                unsigned int val;
        !           564:                val = priv->a->read_csr ( ioaddr, i + 12 ) & 0x0ffff;
        !           565:                /* There may be endianness issues here. */
        !           566:                priv->netdev->hw_addr[2 * i] = val & 0x0ff;
        !           567:                priv->netdev->hw_addr[2 * i + 1] = ( val >> 8 ) & 0x0ff;
        !           568:        }
        !           569: 
        !           570:        for ( i = 0; i < ETH_ALEN; i++ )
        !           571:                promaddr[i] = inb ( ioaddr + i );
        !           572: 
        !           573:        if ( memcmp ( promaddr, priv->netdev->hw_addr, ETH_ALEN ) ||
        !           574:             ! is_valid_ether_addr ( priv->netdev->hw_addr ) ) {
        !           575:                if ( is_valid_ether_addr ( promaddr ) ) {
        !           576:                        DBG ( "CSR address is invalid, using PROM addr\n" );
        !           577:                        memcpy ( priv->netdev->hw_addr, promaddr, ETH_ALEN );
        !           578:                }
        !           579:        }
        !           580: 
        !           581:        /* If ethernet address is not valid, return error */
        !           582:        if ( ! is_valid_ether_addr ( priv->netdev->hw_addr ) )
        !           583:                return -EADDRNOTAVAIL;
        !           584: 
        !           585:        return 0;
        !           586: }
        !           587: 
        !           588: /**
        !           589:  * pcnet32_setup_if_duplex - Sets the NICs used interface and duplex mode
        !           590:  *
        !           591:  * @v priv     Driver private structure
        !           592:  */
        !           593: static void
        !           594: pcnet32_setup_if_duplex ( struct pcnet32_private *priv )
        !           595: {
        !           596:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           597:        u16 val;
        !           598: 
        !           599:        /* Set/Reset autoselect bit */
        !           600:        val = priv->a->read_bcr ( ioaddr, 2 ) & ~2;
        !           601:        if ( priv->options & PCNET32_PORT_ASEL )
        !           602:                val |= 2;
        !           603:        priv->a->write_bcr ( ioaddr, 2, val );
        !           604: 
        !           605:        /* Handle full duplex setting */
        !           606:        if ( priv->full_duplex ) {
        !           607:                val = priv->a->read_bcr ( ioaddr, 9 ) & ~3;
        !           608:                if ( priv->options & PCNET32_PORT_FD ) {
        !           609:                        val |= 1;
        !           610:                        if ( priv->options == ( PCNET32_PORT_FD | PCNET32_PORT_AUI ) )
        !           611:                                val |= 2;
        !           612:                } else if ( priv->options & PCNET32_PORT_ASEL ) {
        !           613:                        /* Workaround of xSeries 250, on for 79C975 only */
        !           614:                        if ( priv->chip_version == 0x2627 )
        !           615:                                val |= 3;
        !           616:                }
        !           617:                priv->a->write_bcr ( ioaddr, 9, val );
        !           618:        }
        !           619: 
        !           620:        /* Set/Reset GPSI bit in test register */
        !           621:        val = priv->a->read_csr ( ioaddr, 124 ) & ~0x10;
        !           622:        if ( ( priv->options & PCNET32_PORT_PORTSEL ) == PCNET32_PORT_GPSI )
        !           623:                val |= 0x10;
        !           624:        priv->a->write_bcr ( ioaddr, 124, val );
        !           625: 
        !           626:        /* Allied Telesyn AT are 100Mbit only and do not negotiate */
        !           627:        u16 subsys_vend_id, subsys_dev_id;
        !           628:        pci_read_config_word ( priv->pci_dev,
        !           629:                               PCI_SUBSYSTEM_VENDOR_ID,
        !           630:                               &subsys_vend_id );
        !           631:        pci_read_config_word ( priv->pci_dev,
        !           632:                               PCI_SUBSYSTEM_ID,
        !           633:                               &subsys_dev_id );
        !           634:        if ( subsys_vend_id == PCI_VENDOR_ID_AT &&
        !           635:             ( ( subsys_dev_id == PCI_SUBDEVICE_ID_AT_2700FX ) ||
        !           636:               ( subsys_dev_id == PCI_SUBDEVICE_ID_AT_2701FX ) ) ) {
        !           637:                priv->options = PCNET32_PORT_FD | PCNET32_PORT_100;
        !           638:        }
        !           639: 
        !           640:        if ( priv->mii && ! ( priv->options & PCNET32_PORT_ASEL ) ) {
        !           641:                /* Disable Auto Negotiation, set 10Mbps, HD */
        !           642:                val = priv->a->read_bcr ( ioaddr, 32 ) & ~0x38;
        !           643:                if ( priv->options & PCNET32_PORT_FD )
        !           644:                        val |= 0x10;
        !           645:                if ( priv->options & PCNET32_PORT_100 )
        !           646:                        val |= 0x08;
        !           647:                priv->a->write_bcr ( ioaddr, 32, val );
        !           648:        } else if ( priv->options & PCNET32_PORT_ASEL ) {
        !           649:                /* 79C970 chips do not have the BCR32 register */
        !           650:                if ( ( priv->chip_version != 0x2420 ) &&
        !           651:                     ( priv->chip_version != 0x2621 ) ) {
        !           652:                        /* Enable Auto Negotiation, setup, disable FD */
        !           653:                        val = priv->a->read_bcr ( ioaddr, 32 ) & ~0x98;
        !           654:                        val |= 0x20;
        !           655:                        priv->a->write_bcr ( ioaddr, 32, val );
        !           656:                }
        !           657:        }
        !           658: }
        !           659: 
        !           660: /**
        !           661:  * pcnet32_hw_start - Starts up the NIC
        !           662:  *
        !           663:  * @v priv     Driver private structure
        !           664:  */
        !           665: static void
        !           666: pcnet32_hw_start ( struct pcnet32_private *priv )
        !           667: {
        !           668:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           669:        int i;
        !           670: 
        !           671:        /* Begin initialization procedure */
        !           672:        priv->a->write_csr ( ioaddr, 0, Init );
        !           673: 
        !           674:        /* Wait for the initialization to be done */
        !           675:        i = 0;
        !           676:        while ( i++ < 100 )
        !           677:                if ( priv->a->read_csr ( ioaddr, 0 ) & InitDone )
        !           678:                        break;
        !           679: 
        !           680:        /* Start the chip */
        !           681:        priv->a->write_csr ( ioaddr, 0, Strt );
        !           682: }
        !           683: 
        !           684: /**
        !           685:  * open - Called when a network interface is made active
        !           686:  *
        !           687:  * @v netdev   Network device
        !           688:  * @ret rc     Return status code, 0 on success, negative value on failure
        !           689:  **/
        !           690: static int
        !           691: pcnet32_open ( struct net_device *netdev )
        !           692: {
        !           693:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           694:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           695:        int rc;
        !           696:        u16 val;
        !           697: 
        !           698:        /* Setup TX and RX descriptors */
        !           699:        if ( ( rc = pcnet32_setup_tx_resources ( priv ) ) != 0 ) {
        !           700:                DBG ( "Error setting up TX resources\n" );
        !           701:                goto err_setup_tx;
        !           702:        }
        !           703: 
        !           704:        if ( ( rc = pcnet32_setup_rx_resources ( priv ) ) != 0 ) {
        !           705:                DBG ( "Error setting up RX resources\n" );
        !           706:                goto err_setup_rx;
        !           707:        }
        !           708: 
        !           709:        /* Reset the chip */
        !           710:        priv->a->reset ( ioaddr );
        !           711: 
        !           712:        /* Switch pcnet32 to 32bit mode */
        !           713:        priv->a->write_bcr ( ioaddr, 20, PCNET32_SWSTYLE_PCNET32 );
        !           714: 
        !           715:        /* Setup the interface and duplex mode */
        !           716:        pcnet32_setup_if_duplex ( priv );
        !           717: 
        !           718:        /* Disable interrupts */
        !           719:        val = priv->a->read_csr ( ioaddr, 3 );
        !           720:        val |= BablMask | MissFrameMask | RxIntMask | TxIntMask | InitDoneMask;
        !           721:        priv->a->write_csr ( ioaddr, 3, val );
        !           722: 
        !           723:        /* Setup initialization block */
        !           724:        pcnet32_setup_init_block ( priv );
        !           725: 
        !           726:        /* Fill in the address of the initialization block */
        !           727:        priv->a->write_csr ( ioaddr, 1,
        !           728:                ( virt_to_bus ( &priv->init_block ) ) & 0xffff );
        !           729:        priv->a->write_csr ( ioaddr, 2,
        !           730:                ( virt_to_bus ( &priv->init_block ) ) >> 16 );
        !           731: 
        !           732:        /* Enable Auto-Pad, disable interrupts */
        !           733:        priv->a->write_csr ( ioaddr, 4, 0x0915 );
        !           734: 
        !           735:        pcnet32_hw_start ( priv );
        !           736: 
        !           737:        return 0;
        !           738: 
        !           739: err_setup_rx:
        !           740:        pcnet32_free_tx_resources ( priv );
        !           741: err_setup_tx:
        !           742:        priv->a->reset( priv->pci_dev->ioaddr );
        !           743:        return rc;
        !           744: }
        !           745: 
        !           746: /**
        !           747:  * transmit - Transmit a packet
        !           748:  *
        !           749:  * @v netdev   Network device
        !           750:  * @v iobuf    I/O buffer
        !           751:  *
        !           752:  * @ret rc     Returns 0 on success, negative on failure
        !           753:  */
        !           754: static int
        !           755: pcnet32_transmit ( struct net_device *netdev, struct io_buffer *iobuf )
        !           756: {
        !           757:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           758:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           759:        uint32_t tx_len = iob_len ( iobuf );
        !           760:        struct pcnet32_tx_desc *tx_curr_desc;
        !           761: 
        !           762:        DBGP ( "pcnet32_transmit\n" );
        !           763: 
        !           764:        if ( priv->tx_fill_ctr == TX_RING_SIZE ) {
        !           765:                DBG ( "Tx overflow\n" );
        !           766:                return -ENOTSUP;
        !           767:        }
        !           768: 
        !           769:        priv->tx_iobuf[priv->tx_curr] = iobuf;
        !           770: 
        !           771:        tx_curr_desc = priv->tx_base + priv->tx_curr;
        !           772: 
        !           773:        /* Configure current descriptor to transmit packet */
        !           774:        tx_curr_desc->length = cpu_to_le16 ( -tx_len );
        !           775:        tx_curr_desc->misc = 0x00000000;
        !           776:        tx_curr_desc->base = cpu_to_le32 ( virt_to_bus ( iobuf->data ) );
        !           777: 
        !           778:        /* Owner changes after the other status fields are set */
        !           779:        wmb();
        !           780:        tx_curr_desc->status =
        !           781:                cpu_to_le16 ( DescOwn | StartOfPacket | EndOfPacket );
        !           782: 
        !           783:        /* Trigger an immediate send poll */
        !           784:        priv->a->write_csr ( ioaddr, 0,
        !           785:                ( priv->irq_enabled ? IntEnable : 0 ) | TxDemand );
        !           786: 
        !           787:        /* Point to the next free descriptor */
        !           788:        priv->tx_curr = ( priv->tx_curr + 1 ) % TX_RING_SIZE;
        !           789: 
        !           790:        /* Increment number of tx descriptors in use */
        !           791:        priv->tx_fill_ctr++;
        !           792: 
        !           793:        return 0;
        !           794: }
        !           795: 
        !           796: /**
        !           797:  * pcnet32_process_tx_packets - Checks for successfully sent packets,
        !           798:  * reports them to iPXE with netdev_tx_complete()
        !           799:  *
        !           800:  * @v netdev   Network device
        !           801:  */
        !           802: static void
        !           803: pcnet32_process_tx_packets ( struct net_device *netdev )
        !           804: {
        !           805:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           806:        struct pcnet32_tx_desc *tx_curr_desc;
        !           807: 
        !           808:        DBGP ( "pcnet32_process_tx_packets\n" );
        !           809: 
        !           810:        while ( priv->tx_tail != priv->tx_curr ) {
        !           811:                tx_curr_desc = priv->tx_base + priv->tx_tail;
        !           812: 
        !           813:                u16 status = le16_to_cpu ( tx_curr_desc->status );
        !           814: 
        !           815:                DBG ( "Before OWN bit check, status: %#08x\n", status );
        !           816: 
        !           817:                /* Skip this descriptor if hardware still owns it */
        !           818:                if ( status & DescOwn )
        !           819:                        break;
        !           820: 
        !           821:                DBG ( "Transmitted packet.\n" );
        !           822:                DBG ( "priv->tx_fill_ctr= %d\n", priv->tx_fill_ctr );
        !           823:                DBG ( "priv->tx_tail    = %d\n", priv->tx_tail );
        !           824:                DBG ( "priv->tx_curr    = %d\n", priv->tx_curr );
        !           825:                DBG ( "tx_curr_desc     = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
        !           826: 
        !           827:                /* This packet is ready for completion */
        !           828:                netdev_tx_complete ( netdev, priv->tx_iobuf[priv->tx_tail]);
        !           829: 
        !           830:                /* Clear the descriptor */
        !           831:                memset ( tx_curr_desc, 0, sizeof(*tx_curr_desc) );
        !           832: 
        !           833:                /* Reduce the number of tx descriptors in use */
        !           834:                priv->tx_fill_ctr--;
        !           835: 
        !           836:                /* Go to next available descriptor */
        !           837:                priv->tx_tail = ( priv->tx_tail + 1 ) % TX_RING_SIZE;
        !           838:        }
        !           839: }
        !           840: 
        !           841: /**
        !           842:  * pcnet32_process_rx_packets - Checks for received packets, reports them
        !           843:  * to iPXE with netdev_rx() or netdev_rx_err() if there was an error receiving
        !           844:  * the packet
        !           845:  *
        !           846:  * @v netdev   Network device
        !           847:  */
        !           848: static void
        !           849: pcnet32_process_rx_packets ( struct net_device *netdev )
        !           850: {
        !           851:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           852:        struct pcnet32_rx_desc *rx_curr_desc;
        !           853:        u16 status;
        !           854:        u32 len;
        !           855:        int i;
        !           856: 
        !           857:        DBGP ( "pcnet32_process_rx_packets\n" );
        !           858: 
        !           859:        for ( i = 0; i < RX_RING_SIZE; i++ ) {
        !           860:                rx_curr_desc = priv->rx_base + priv->rx_curr;
        !           861: 
        !           862:                status = le16_to_cpu ( rx_curr_desc->status );
        !           863:                rmb();
        !           864: 
        !           865:                DBG ( "Before OWN bit check, status: %#08x\n", status );
        !           866: 
        !           867:                /* Skip this descriptor if hardware still owns it */
        !           868:                if ( status & DescOwn )
        !           869:                        break;
        !           870: 
        !           871:                /* We own the descriptor, but it has not been refilled yet */
        !           872:                if ( priv->rx_iobuf[priv->rx_curr] == NULL )
        !           873:                        break;
        !           874: 
        !           875:                DBG ( "Received packet.\n" );
        !           876:                DBG ( "priv->rx_curr    = %d\n", priv->rx_curr );
        !           877:                DBG ( "rx_len           = %d\n",
        !           878:                      ( le32_to_cpu ( rx_curr_desc->msg_length ) & 0xfff ) - 4 );
        !           879:                DBG ( "rx_curr_desc     = %#08lx\n",
        !           880:                      virt_to_bus ( rx_curr_desc ) );
        !           881: 
        !           882:                /* Check ERR bit */
        !           883:                if ( status & 0x4000 ) {
        !           884:                        netdev_rx_err ( netdev, priv->rx_iobuf[priv->rx_curr],
        !           885:                                        -EINVAL );
        !           886:                        DBG ( "Corrupted packet received!\n");
        !           887:                } else {
        !           888:                        /* Adjust size of the iobuf to reflect received data */
        !           889:                        len = ( le32_to_cpu ( rx_curr_desc->msg_length ) & 0xfff ) - 4;
        !           890:                        iob_put ( priv->rx_iobuf[priv->rx_curr], len );
        !           891: 
        !           892:                        /* Add this packet to the receive queue */
        !           893:                        netdev_rx ( netdev, priv->rx_iobuf[priv->rx_curr] );
        !           894:                }
        !           895: 
        !           896:                /* Invalidate iobuf and descriptor */
        !           897:                priv->rx_iobuf[priv->rx_curr] = NULL;
        !           898:                memset ( rx_curr_desc, 0, sizeof(*rx_curr_desc) );
        !           899: 
        !           900:                /* Point to the next free descriptor */
        !           901:                priv->rx_curr = ( priv->rx_curr + 1 ) % RX_RING_SIZE;
        !           902:        }
        !           903: 
        !           904:        /* Allocate new iobufs where needed */
        !           905:        pcnet32_refill_rx_ring ( priv );
        !           906: }
        !           907: 
        !           908: /**
        !           909:  * poll - Poll for received packets
        !           910:  *
        !           911:  * @v netdev   Network device
        !           912:  */
        !           913: static void
        !           914: pcnet32_poll ( struct net_device *netdev )
        !           915: {
        !           916:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           917:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           918:        u16 status;
        !           919: 
        !           920:        DBGP ( "pcnet32_poll\n" );
        !           921: 
        !           922:        status = priv->a->read_csr ( ioaddr, 0 );
        !           923: 
        !           924:        /* Clear interrupts */
        !           925:        priv->a->write_csr ( ioaddr, 0, status );
        !           926: 
        !           927:        DBG ( "pcnet32_poll: mask = %#04x, status = %#04x\n",
        !           928:                priv->a->read_csr ( ioaddr, 3 ), status );
        !           929: 
        !           930:        /* Return when RINT or TINT are not set */
        !           931:        if ( ( status & 0x0500 ) == 0x0000 )
        !           932:                return;
        !           933: 
        !           934:        /* Process transmitted packets */
        !           935:        pcnet32_process_tx_packets ( netdev );
        !           936: 
        !           937:        /* Process received packets */
        !           938:        pcnet32_process_rx_packets ( netdev );
        !           939: }
        !           940: 
        !           941: /**
        !           942:  * close - Disable network interface
        !           943:  *
        !           944:  * @v netdev   network interface device structure
        !           945:  **/
        !           946: static void
        !           947: pcnet32_close ( struct net_device *netdev )
        !           948: {
        !           949:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !           950:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           951: 
        !           952:        DBGP ( "pcnet32_close\n" );
        !           953: 
        !           954:        /* Reset the chip */
        !           955:        pcnet32_wio_reset ( ioaddr );
        !           956: 
        !           957:        /* Stop the PCNET32 - it occasionally polls memory if we don't */
        !           958:        priv->a->write_csr ( ioaddr, 0, Stop );
        !           959: 
        !           960:        /* Switch back to 16bit mode to avoid problems with dumb
        !           961:         * DOS packet driver after a warm reboot */
        !           962:        priv->a->write_bcr ( ioaddr, 20, PCNET32_SWSTYLE_LANCE );
        !           963: 
        !           964:        pcnet32_free_rx_resources ( priv );
        !           965:        pcnet32_free_tx_resources ( priv );
        !           966: }
        !           967: 
        !           968: static void pcnet32_irq_enable ( struct pcnet32_private *priv )
        !           969: {
        !           970:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           971:        u16 val;
        !           972: 
        !           973:        DBGP ( "pcnet32_irq_enable\n" );
        !           974: 
        !           975:        /* Enable TINT and RINT masks */
        !           976:        val = priv->a->read_csr ( ioaddr, 3 );
        !           977:        val &= ~( RxIntMask | TxIntMask );
        !           978:        priv->a->write_csr ( ioaddr, 3, val );
        !           979: 
        !           980:        /* Enable interrupts */
        !           981:        priv->a->write_csr ( ioaddr, 0, IntEnable );
        !           982: 
        !           983:        priv->irq_enabled = 1;
        !           984: }
        !           985: 
        !           986: static void pcnet32_irq_disable ( struct pcnet32_private *priv )
        !           987: {
        !           988:        unsigned long ioaddr = priv->pci_dev->ioaddr;
        !           989: 
        !           990:        DBGP ( "pcnet32_irq_disable\n" );
        !           991: 
        !           992:        priv->a->write_csr ( ioaddr, 0, 0x0000 );
        !           993: 
        !           994:        priv->irq_enabled = 0;
        !           995: }
        !           996: 
        !           997: /**
        !           998:  * irq - enable or disable interrupts
        !           999:  *
        !          1000:  * @v netdev    network adapter
        !          1001:  * @v action    requested interrupt action
        !          1002:  **/
        !          1003: static void
        !          1004: pcnet32_irq ( struct net_device *netdev, int action )
        !          1005: {
        !          1006:        struct pcnet32_private *priv = netdev_priv ( netdev );
        !          1007: 
        !          1008:        DBGP ( "pcnet32_irq\n" );
        !          1009: 
        !          1010:        switch ( action ) {
        !          1011:        case 0:
        !          1012:                pcnet32_irq_disable ( priv );
        !          1013:                break;
        !          1014:        default:
        !          1015:                pcnet32_irq_enable ( priv );
        !          1016:                break;
        !          1017:        }
        !          1018: }
        !          1019: 
        !          1020: static struct net_device_operations pcnet32_operations = {
        !          1021:        .open           = pcnet32_open,
        !          1022:        .transmit       = pcnet32_transmit,
        !          1023:        .poll           = pcnet32_poll,
        !          1024:        .close          = pcnet32_close,
        !          1025:        .irq            = pcnet32_irq,
        !          1026: };
        !          1027: 
        !          1028: /**
        !          1029:  * probe - Initial configuration of NIC
        !          1030:  *
        !          1031:  * @v pdev     PCI device
        !          1032:  * @v ent      PCI IDs
        !          1033:  *
        !          1034:  * @ret rc     Return status code
        !          1035:  **/
        !          1036: static int
        !          1037: pcnet32_probe ( struct pci_device *pdev )
        !          1038: {
        !          1039:        struct net_device *netdev;
        !          1040:        struct pcnet32_private *priv;
        !          1041:        unsigned long ioaddr;
        !          1042:        int rc;
        !          1043: 
        !          1044:        DBGP ( "pcnet32_probe\n" );
        !          1045: 
        !          1046:        DBG ( "Found %s, vendor = %#04x, device = %#04x\n",
        !          1047:                pdev->id->name, pdev->id->vendor, pdev->id->device );
        !          1048: 
        !          1049:        /* Allocate our private data */
        !          1050:        netdev = alloc_etherdev ( sizeof ( *priv ) );
        !          1051:        if ( ! netdev ) {
        !          1052:                rc = -ENOMEM;
        !          1053:                goto err_alloc_etherdev;
        !          1054:        }
        !          1055: 
        !          1056:        /* Link our operations to the netdev struct */
        !          1057:        netdev_init ( netdev, &pcnet32_operations );
        !          1058: 
        !          1059:        /* Link the PCI device to the netdev struct */
        !          1060:        pci_set_drvdata ( pdev, netdev );
        !          1061:        netdev->dev = &pdev->dev;
        !          1062: 
        !          1063:        /* Get a reference to our private data */
        !          1064:        priv = netdev_priv ( netdev );
        !          1065: 
        !          1066:        /* We'll need these set up for the rest of the routines */
        !          1067:        priv->pci_dev = pdev;
        !          1068:        priv->netdev = netdev;
        !          1069: 
        !          1070:        ioaddr = pdev->ioaddr;
        !          1071: 
        !          1072:        /* Only use irqs under UNDI */
        !          1073:        priv->irq_enabled = 0;
        !          1074: 
        !          1075:        /* Reset the chip */
        !          1076:        pcnet32_wio_reset ( ioaddr );
        !          1077: 
        !          1078:        if ( ( rc = pcnet32_set_ops ( priv ) ) != 0 ) {
        !          1079:                DBG ( "Setting driver operations failed\n");
        !          1080:                goto err_set_ops;
        !          1081:        }
        !          1082: 
        !          1083:        if ( ( rc = pcnet32_chip_detect ( priv ) ) != 0 ) {
        !          1084:                DBG ( "pcnet32_chip_detect failed\n" );
        !          1085:                goto err_chip_detect;
        !          1086:        }
        !          1087: 
        !          1088:        /* Enter bus mastering mode */
        !          1089:        adjust_pci_device ( pdev );
        !          1090: 
        !          1091:        /* Verify and get MAC address */
        !          1092:        if ( ( rc = pcnet32_setup_mac_addr ( priv ) ) != 0 ) {
        !          1093:                DBG ( "Setting MAC address failed\n" );
        !          1094:                goto err_mac_addr;
        !          1095:        }
        !          1096: 
        !          1097:        DBG ( "IO Addr 0x%lX, MAC Addr %s\n", ioaddr,
        !          1098:                eth_ntoa ( netdev->hw_addr ) );
        !          1099: 
        !          1100:        priv->options = PCNET32_PORT_ASEL;
        !          1101: 
        !          1102:        /* Detect special T1/E1 WAN card by checking for MAC address */
        !          1103:        if ( netdev->hw_addr[0] == 0x00 &&
        !          1104:             netdev->hw_addr[1] == 0xE0 &&
        !          1105:             netdev->hw_addr[2] == 0x75 )
        !          1106:                priv->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
        !          1107: 
        !          1108:        /* Probe the PHY so we can check link state and speed */
        !          1109:        pcnet32_setup_probe_phy ( priv );
        !          1110: 
        !          1111:        if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
        !          1112:                DBG ( "Error registering netdev\n" );
        !          1113:                goto err_register;
        !          1114:        }
        !          1115: 
        !          1116:        netdev_link_up ( netdev );
        !          1117: 
        !          1118:        return 0;
        !          1119: 
        !          1120: err_register:
        !          1121:        netdev_put ( netdev );
        !          1122: err_chip_detect:
        !          1123: err_set_ops:
        !          1124: err_alloc_etherdev:
        !          1125: err_mac_addr:
        !          1126:        return rc;
        !          1127: }
        !          1128: 
        !          1129: /**
        !          1130:  * remove - Device Removal Routine
        !          1131:  *
        !          1132:  * @v pdev PCI device information struct
        !          1133:  **/
        !          1134: static void
        !          1135: pcnet32_remove ( struct pci_device *pdev )
        !          1136: {
        !          1137:        struct net_device *netdev = pci_get_drvdata ( pdev );
        !          1138:        unsigned long ioaddr = pdev->ioaddr;
        !          1139: 
        !          1140:        DBGP ( "pcnet32_remove\n" );
        !          1141: 
        !          1142:        /* Reset the chip */
        !          1143:        pcnet32_wio_reset ( ioaddr );
        !          1144: 
        !          1145:        unregister_netdev ( netdev );
        !          1146:        netdev_nullify ( netdev );
        !          1147:        netdev_put ( netdev );
        !          1148: }
        !          1149: 
        !          1150: static struct pci_device_id pcnet32_nics[] = {
        !          1151:        PCI_ROM(0x1022, 0x2000, "pcnet32", "AMD PCnet/PCI", 0),
        !          1152:        PCI_ROM(0x1022, 0x2625, "pcnetfastiii", "AMD PCNet FAST III", 0),
        !          1153:        PCI_ROM(0x1022, 0x2001, "amdhomepna", "AMD PCnet/HomePNA", 0),
        !          1154: };
        !          1155: 
        !          1156: struct pci_driver pcnet32_driver __pci_driver = {
        !          1157:        .ids            = pcnet32_nics,
        !          1158:        .id_count       = ARRAY_SIZE ( pcnet32_nics ),
        !          1159:        .probe          = pcnet32_probe,
        !          1160:        .remove         = pcnet32_remove,
        !          1161: };

unix.superglobalmegacorp.com

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