Annotation of qemu/roms/ipxe/src/drivers/net/natsemi.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:    natsemi.c - iPXE driver for the NatSemi DP8381x series.
                      3:  
                      4:    Based on:
                      5: 
                      6:    natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
                      7: 
                      8:    Copyright (C) 2001 Entity Cyber, Inc.
                      9:    
                     10:    This development of this Etherboot driver was funded by 
                     11:    
                     12:       Sicom Systems: http://www.sicompos.com/
                     13:    
                     14:    Author: Marty Connor <[email protected]>
                     15:    Adapted from a Linux driver which was written by Donald Becker
                     16:    
                     17:    This software may be used and distributed according to the terms
                     18:    of the GNU Public License (GPL), incorporated herein by reference.
                     19:    
                     20:    Original Copyright Notice:
                     21:    
                     22:    Written/copyright 1999-2001 by Donald Becker.
                     23:    
                     24:    This software may be used and distributed according to the terms of
                     25:    the GNU General Public License (GPL), incorporated herein by reference.
                     26:    Drivers based on or derived from this code fall under the GPL and must
                     27:    retain the authorship, copyright and license notice.  This file is not
                     28:    a complete program and may only be used when the entire operating
                     29:    system is licensed under the GPL.  License for under other terms may be
                     30:    available.  Contact the original author for details.
                     31:    
                     32:    The original author may be reached as [email protected], or at
                     33:    Scyld Computing Corporation
                     34:    410 Severn Ave., Suite 210
                     35:    Annapolis MD 21403
                     36:    
                     37:    Support information and updates available at
                     38:    http://www.scyld.com/network/netsemi.html
                     39:    
                     40:    References:
                     41:    
                     42:    http://www.scyld.com/expert/100mbps.html
                     43:    http://www.scyld.com/expert/NWay.html
                     44:    Datasheet is available from:
                     45:    http://www.national.com/pf/DP/DP83815.html
                     46: 
                     47: */
                     48: 
                     49: FILE_LICENCE ( GPL_ANY );
                     50: 
                     51: /* Revision History */
                     52: 
                     53: /*
                     54:   02 Jul 2007  Udayan Kumar     1.2 ported the driver from etherboot to iPXE API.
                     55:                                     Fully rewritten,adapting the old driver.
                     56:                                     Added a circular buffer for transmit and receive.
                     57:                                     transmit routine will not wait for transmission to finish.
                     58:                                     poll routine deals with it.
                     59:   13 Dec 2003  Tim Legge         1.1 Enabled Multicast Support
                     60:   29 May 2001  Marty Connor     1.0 Initial Release. Tested with Netgear FA311 and FA312 boards
                     61: */
                     62: 
                     63: #include <stdint.h>
                     64: #include <stdlib.h>
                     65: #include <stdio.h>
                     66: #include <string.h>
                     67: #include <ipxe/io.h>
                     68: #include <errno.h>
                     69: #include <byteswap.h>
                     70: #include <unistd.h>
                     71: #include <ipxe/pci.h>
                     72: #include <ipxe/if_ether.h>
                     73: #include <ipxe/ethernet.h>
                     74: #include <ipxe/iobuf.h>
                     75: #include <ipxe/netdevice.h>
                     76: #include <ipxe/spi_bit.h>
                     77: #include <ipxe/threewire.h>
                     78: #include <ipxe/nvo.h>
                     79: #include "natsemi.h"
                     80: 
                     81: /*  Function Prototypes: */
                     82:  
                     83: static int natsemi_spi_read_bit ( struct bit_basher *, unsigned int );
                     84: static void natsemi_spi_write_bit ( struct bit_basher *,unsigned int, unsigned long ); 
                     85: static void natsemi_init_eeprom ( struct natsemi_private * ); 
                     86: static int natsemi_probe (struct pci_device *pci);
                     87: static void natsemi_reset (struct net_device *netdev);
                     88: static int natsemi_open (struct net_device *netdev);
                     89: static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf);
                     90: static void natsemi_poll (struct net_device *netdev);
                     91: static void natsemi_close (struct net_device *netdev);
                     92: static void natsemi_irq (struct net_device *netdev, int enable);
                     93: static void natsemi_remove (struct pci_device *pci);
                     94: 
                     95: /** natsemi net device operations */
                     96: static struct net_device_operations natsemi_operations = {
                     97:         .open           = natsemi_open,
                     98:         .close          = natsemi_close,
                     99:         .transmit       = natsemi_transmit,
                    100:         .poll           = natsemi_poll,
                    101:        .irq            = natsemi_irq,
                    102: };
                    103: 
                    104: static int natsemi_spi_read_bit ( struct bit_basher *basher,
                    105:                              unsigned int bit_id ) {
                    106:        struct natsemi_private *np = container_of ( basher, struct natsemi_private,
                    107:                                                 spibit.basher );
                    108:        uint8_t mask = natsemi_ee_bits[bit_id];
                    109:        uint8_t eereg;
                    110: 
                    111:        eereg = inb ( np->ioaddr + EE_REG );
                    112:        return ( eereg & mask );
                    113: }
                    114: 
                    115: static void natsemi_spi_write_bit ( struct bit_basher *basher,
                    116:                                unsigned int bit_id, unsigned long data ) {
                    117:        struct natsemi_private *np = container_of ( basher, struct natsemi_private,
                    118:                                                 spibit.basher );
                    119:        uint8_t mask = natsemi_ee_bits[bit_id];
                    120:        uint8_t eereg;
                    121: 
                    122:        eereg = inb ( np->ioaddr + EE_REG );
                    123:        eereg &= ~mask;
                    124:        eereg |= ( data & mask );
                    125:        outb ( eereg, np->ioaddr + EE_REG );
                    126: }
                    127: 
                    128: static struct bit_basher_operations natsemi_basher_ops = {
                    129:        .read = natsemi_spi_read_bit,
                    130:        .write = natsemi_spi_write_bit,
                    131: };
                    132: 
                    133: /*
                    134:  * Set up for EEPROM access
                    135:  *
                    136:  * @v NAT              NATSEMI NIC
                    137:  */
                    138: static void natsemi_init_eeprom ( struct natsemi_private *np ) {
                    139: 
                    140:        /* Initialise three-wire bus 
                    141:         */
                    142:        np->spibit.basher.op = &natsemi_basher_ops;
                    143:        np->spibit.bus.mode = SPI_MODE_THREEWIRE;
                    144:        np->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
                    145:        init_spi_bit_basher ( &np->spibit );
                    146: 
                    147:        /*natsemi DP 83815 only supports at93c46
                    148:         */
                    149:        init_at93c46 ( &np->eeprom, 16 );
                    150:        np->eeprom.bus = &np->spibit.bus;
                    151: 
                    152:        /* It looks that this portion of EEPROM can be used for
                    153:         * non-volatile stored options. Data sheet does not talk about
                    154:         * this region.  Currently it is not working. But with some
                    155:         * efforts it can.
                    156:         */
                    157:        nvo_init ( &np->nvo, &np->eeprom.nvs, 0x0c, 0x68, NULL, NULL );
                    158: }
                    159: 
                    160: /**
                    161:  * Probe PCI device
                    162:  *
                    163:  * @v pci      PCI device
                    164:  * @v id       PCI ID
                    165:  * @ret rc     Return status code
                    166:  */
                    167: static int natsemi_probe (struct pci_device *pci) {
                    168:        struct net_device *netdev;
                    169:        struct natsemi_private *np = NULL;
                    170:        uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
                    171:        uint8_t last=0,last1=0;
                    172:        uint8_t prev_bytes[2];
                    173:        int i;
                    174:        int rc;
                    175: 
                    176:        /* Allocate net device 
                    177:         */
                    178:        netdev = alloc_etherdev (sizeof (*np));
                    179:        if (! netdev) 
                    180:                return -ENOMEM;
                    181: 
                    182:        netdev_init (netdev, &natsemi_operations);
                    183:        np = netdev->priv;
                    184:        pci_set_drvdata (pci, netdev);
                    185:        netdev->dev = &pci->dev;
                    186:        memset (np, 0, sizeof (*np));
                    187:        np->ioaddr = pci->ioaddr;
                    188: 
                    189:        adjust_pci_device (pci);
                    190: 
                    191:        natsemi_reset (netdev);
                    192:        natsemi_init_eeprom ( np );
                    193:        nvs_read ( &np->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
                    194:        nvs_read ( &np->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
                    195: 
                    196:        /* decoding the MAC address read from NVS 
                    197:         * and save it in netdev->ll_addr
                    198:          */
                    199:        last = prev_bytes[1] >> 7;
                    200:        for ( i = 0 ; i < ETH_ALEN ; i++ ) {
                    201:                last1 = ll_addr_encoded[i] >> 7;
                    202:                netdev->hw_addr[i] = ll_addr_encoded[i] << 1 | last;
                    203:                last = last1;
                    204:        }
                    205: 
                    206:        if ((rc = register_netdev (netdev)) != 0)
                    207:                goto err_register_netdev;
                    208: 
                    209:        /* Mark as link up; we don't yet handle link state */
                    210:        netdev_link_up ( netdev );
                    211: 
                    212:        return 0;
                    213: 
                    214: err_register_netdev:
                    215: 
                    216:        natsemi_reset (netdev);
                    217:        netdev_put (netdev);
                    218:        return rc;
                    219: }
                    220: 
                    221: /**
                    222:  * Remove PCI device
                    223:  *
                    224:  * @v pci      PCI device
                    225:  */
                    226: static void natsemi_remove (struct pci_device *pci) {
                    227:        struct net_device *netdev = pci_get_drvdata (pci);
                    228:  
                    229:        unregister_netdev (netdev);
                    230:        natsemi_reset (netdev);
                    231:        netdev_nullify ( netdev );
                    232:        netdev_put (netdev);
                    233: }
                    234: 
                    235: /**
                    236:  * Reset NIC
                    237:  *
                    238:  * @v          NATSEMI NIC
                    239:  *
                    240:  * Issues a hardware reset and waits for the reset to complete.
                    241:  */
                    242: static void natsemi_reset (struct net_device *netdev) 
                    243: {
                    244:        struct natsemi_private *np = netdev->priv;
                    245:        int i;
                    246:         u32 cfg;
                    247:         u32 wcsr;
                    248:         u32 rfcr;
                    249:         u16 pmatch[3];
                    250:         u16 sopass[3];
                    251: 
                    252:        natsemi_irq (netdev, 0);
                    253: 
                    254:         /*
                    255:          * Resetting the chip causes some registers to be lost.
                    256:          * Natsemi suggests NOT reloading the EEPROM while live, so instead
                    257:          * we save the state that would have been loaded from EEPROM
                    258:          * on a normal power-up (see the spec EEPROM map).
                    259:          */
                    260: 
                    261:         /* CFG */
                    262:         cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE;
                    263: 
                    264:         /* WCSR */
                    265:         wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE;
                    266: 
                    267:         /* RFCR */
                    268:         rfcr = inl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
                    269: 
                    270:         /* PMATCH */
                    271:         for (i = 0; i < 3; i++) {
                    272:                outl(i*2, np->ioaddr + RxFilterAddr);
                    273:                pmatch[i] = inw(np->ioaddr + RxFilterData);
                    274:         }
                    275: 
                    276:         /* SOPAS */
                    277:         for (i = 0; i < 3; i++) {
                    278:                outl(0xa+(i*2), np->ioaddr + RxFilterAddr);
                    279:                sopass[i] = inw(np->ioaddr + RxFilterData);
                    280:         }
                    281: 
                    282:         /* now whack the chip */
                    283:         outl(ChipReset, np->ioaddr + ChipCmd);
                    284:         for (i=0; i<NATSEMI_HW_TIMEOUT; i++) {
                    285:                if (! (inl (np->ioaddr + ChipCmd) & ChipReset))
                    286:                       break;
                    287:                udelay(5);
                    288:         }
                    289:         if (i == NATSEMI_HW_TIMEOUT) {
                    290:                DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5);
                    291:         }
                    292: 
                    293:         /* restore CFG */
                    294:         cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
                    295:        cfg &= ~(CfgExtPhy | CfgPhyDis);
                    296:         outl (cfg, np->ioaddr + ChipConfig);
                    297: 
                    298:         /* restore WCSR */
                    299:         wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
                    300:         outl (wcsr, np->ioaddr + WOLCmd);
                    301: 
                    302:         /* read RFCR */
                    303:         rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
                    304: 
                    305:         /* restore PMATCH */
                    306:         for (i = 0; i < 3; i++) {
                    307:                outl (i*2, np->ioaddr + RxFilterAddr);
                    308:                outw (pmatch[i], np->ioaddr + RxFilterData);
                    309:         }
                    310:         for (i = 0; i < 3; i++) {
                    311:                outl (0xa+(i*2), np->ioaddr + RxFilterAddr);
                    312:                outw (sopass[i], np->ioaddr + RxFilterData);
                    313:         }
                    314:         /* restore RFCR */
                    315:         outl (rfcr, np->ioaddr + RxFilterAddr);
                    316: }
                    317: 
                    318: /**
                    319:  * Open NIC
                    320:  *
                    321:  * @v netdev           Net device
                    322:  * @ret rc             Return status code
                    323:  */
                    324: static int natsemi_open (struct net_device *netdev)
                    325: {
                    326:        struct natsemi_private *np = netdev->priv;
                    327:        uint32_t tx_config, rx_config;
                    328:        int i;
                    329:        
                    330:        /* Disable PME:
                    331:          * The PME bit is initialized from the EEPROM contents.
                    332:          * PCI cards probably have PME disabled, but motherboard
                    333:          * implementations may have PME set to enable WakeOnLan. 
                    334:          * With PME set the chip will scan incoming packets but
                    335:          * nothing will be written to memory. 
                    336:          */
                    337:         outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun);
                    338: 
                    339:        /* Set MAC address in NIC
                    340:         */
                    341:        for (i = 0 ; i < ETH_ALEN ; i+=2) {
                    342:                outl (i, np->ioaddr + RxFilterAddr);
                    343:                outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
                    344:                       np->ioaddr + RxFilterData);
                    345:        }
                    346: 
                    347:        /* Setup Tx Ring 
                    348:         */
                    349:        np->tx_cur = 0;
                    350:        np->tx_dirty = 0;
                    351:        for (i = 0 ; i < TX_RING_SIZE ; i++) {
                    352:                np->tx[i].link   = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
                    353:                np->tx[i].cmdsts = 0;
                    354:                np->tx[i].bufptr = 0;
                    355:        }
                    356:        outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
                    357: 
                    358:        DBG ("Natsemi Tx descriptor loaded with: %#08x\n",
                    359:             inl (np->ioaddr + TxRingPtr));
                    360: 
                    361:        /* Setup RX ring
                    362:         */
                    363:        np->rx_cur = 0;
                    364:        for (i = 0 ; i < NUM_RX_DESC ; i++) {
                    365:                np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
                    366:                if (! np->iobuf[i])
                    367:                        goto memory_alloc_err;
                    368:                np->rx[i].link   = virt_to_bus ((i + 1 < NUM_RX_DESC) 
                    369:                                                ? &np->rx[i + 1] : &np->rx[0]);
                    370:                np->rx[i].cmdsts = RX_BUF_SIZE;
                    371:                np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
                    372:                DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i, 
                    373:                      &np->iobuf[i],  &np->iobuf[i]->data);
                    374:        }
                    375:        outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
                    376: 
                    377:        DBG ("Natsemi Rx descriptor loaded with: %#08x\n",
                    378:              inl (np->ioaddr + RxRingPtr));            
                    379: 
                    380:        /* Setup RX Filter 
                    381:         */
                    382:        outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
                    383:              np->ioaddr + RxFilterAddr);
                    384: 
                    385:        /* Initialize other registers. 
                    386:         * Configure the PCI bus bursts and FIFO thresholds. 
                    387:         * Configure for standard, in-spec Ethernet. 
                    388:         */
                    389:        if (inl (np->ioaddr + ChipConfig) & 0x20000000) {       /* Full duplex */
                    390:                DBG ("Full duplex\n");
                    391:                tx_config = 0xD0801002 |  0xC0000000;
                    392:                rx_config = 0x10000020 |  0x10000000;
                    393:        } else {
                    394:                DBG ("Half duplex\n");
                    395:                tx_config = 0x10801002 & ~0xC0000000;
                    396:                rx_config = 0x00000020 & ~0x10000000;
                    397:        }
                    398:        outl (tx_config, np->ioaddr + TxConfig);
                    399:        outl (rx_config, np->ioaddr + RxConfig);
                    400: 
                    401:        DBG ("Tx config register = %#08x Rx config register = %#08x\n", 
                    402:                inl (np->ioaddr + TxConfig),
                    403:               inl (np->ioaddr + RxConfig));
                    404: 
                    405:        /*Set the Interrupt Mask register
                    406:         */
                    407:        outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
                    408:        /*start the receiver 
                    409:         */
                    410:         outl (RxOn, np->ioaddr + ChipCmd);
                    411:        
                    412:        return 0;
                    413:                       
                    414: memory_alloc_err:
                    415: 
                    416:        /* Frees any allocated buffers when memory
                    417:         * for all buffers requested is not available
                    418:         */
                    419:        i = 0;
                    420:        while (np->rx[i].cmdsts == RX_BUF_SIZE) {
                    421:                free_iob (np->iobuf[i]);
                    422:                i++;
                    423:        }
                    424:        return -ENOMEM; 
                    425: }
                    426: 
                    427: /**
                    428:  * Close NIC
                    429:  *
                    430:  * @v netdev           Net device
                    431:  */
                    432: static void natsemi_close (struct net_device *netdev) 
                    433: {
                    434:        struct natsemi_private *np = netdev->priv;
                    435:        int i;
                    436: 
                    437:        natsemi_reset (netdev);
                    438: 
                    439:        for (i = 0; i < NUM_RX_DESC ; i++) {
                    440:                free_iob (np->iobuf[i]);
                    441:        }
                    442: }
                    443: 
                    444: /** 
                    445:  * Transmit packet
                    446:  *
                    447:  * @v netdev   Network device
                    448:  * @v iobuf    I/O buffer
                    449:  * @ret rc     Return status code
                    450:  */
                    451: static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
                    452: {
                    453:        struct natsemi_private *np = netdev->priv;
                    454: 
                    455:        if (np->tx[np->tx_cur].cmdsts != 0) {
                    456:                DBG ("TX overflow\n");
                    457:                return -ENOBUFS;
                    458:        }
                    459: 
                    460:        /* Used by netdev_tx_complete ()
                    461:         */
                    462:        np->tx_iobuf[np->tx_cur] = iobuf;
                    463: 
                    464:        /* Pad and align packet has not been used because its not required 
                    465:         * by the hardware.
                    466:         *      iob_pad (iobuf, ETH_ZLEN); 
                    467:         * can be used to achieve it, if required
                    468:         */
                    469: 
                    470:        /* Add the packet to TX ring
                    471:         */
                    472:        np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
                    473:        np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
                    474: 
                    475:        DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur,
                    476:             virt_to_bus (&iobuf->data), iob_len (iobuf));
                    477: 
                    478:        /* increment the circular buffer pointer to the next buffer location
                    479:         */
                    480:        np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
                    481: 
                    482:        /*start the transmitter 
                    483:         */
                    484:         outl (TxOn, np->ioaddr + ChipCmd);
                    485: 
                    486:        return 0;
                    487: }
                    488: 
                    489: /** 
                    490:  * Poll for received packets
                    491:  *
                    492:  * @v netdev   Network device
                    493:  */
                    494: static void natsemi_poll (struct net_device *netdev)
                    495: {
                    496:        struct natsemi_private *np = netdev->priv;
                    497:        unsigned int tx_status;
                    498:        unsigned int rx_status;
                    499:        unsigned int intr_status;
                    500:        unsigned int rx_len;
                    501:        struct io_buffer *rx_iob;
                    502:        int i;
                    503:        
                    504:        /* read the interrupt register
                    505:         */
                    506:        intr_status = inl (np->ioaddr + IntrStatus);
                    507: 
                    508:        if (!intr_status)
                    509:                goto end;
                    510: 
                    511:         DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
                    512: 
                    513:        /* Check status of transmitted packets
                    514:         */
                    515:        i = np->tx_dirty;
                    516:        while (i != np->tx_cur) {
                    517:                tx_status = np->tx[np->tx_dirty].cmdsts;
                    518: 
                    519:                DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
                    520:                     np->tx_dirty, np->tx_cur, tx_status);
                    521:                
                    522:                if (tx_status & OWN) 
                    523:                        break;
                    524: 
                    525:                if (! (tx_status & DescPktOK)) {
                    526:                        netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
                    527:                        DBG ("Error transmitting packet, tx_status: %#08x\n",
                    528:                             tx_status);
                    529:                } else {
                    530:                        netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
                    531:                        DBG ("Success transmitting packet\n");
                    532:                }
                    533: 
                    534:                np->tx[np->tx_dirty].cmdsts = 0;
                    535:                np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
                    536:                i = (i + 1) % TX_RING_SIZE;
                    537:        }
                    538:        
                    539:        /* Process received packets 
                    540:         */
                    541:        rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts; 
                    542:        while ((rx_status & OWN)) {
                    543:                rx_len = (rx_status & DSIZE) - CRC_SIZE;
                    544: 
                    545:                 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
                    546:                      np->rx_cur, rx_status, rx_len);
                    547:                 
                    548:                if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
                    549:                        netdev_rx_err (netdev, NULL, -EINVAL);
                    550: 
                    551:                        DBG ("natsemi_poll: Corrupted packet received!"
                    552:                             " Status = %#08x\n",
                    553:                              np->rx[np->rx_cur].cmdsts);
                    554: 
                    555:                } else  {
                    556: 
                    557: 
                    558:                        /* If unable allocate space for this packet,
                    559:                         *  try again next poll
                    560:                         */
                    561:                        rx_iob = alloc_iob (rx_len);
                    562:                        if (! rx_iob) 
                    563:                                goto end;
                    564:                        memcpy (iob_put (rx_iob, rx_len), 
                    565:                                np->iobuf[np->rx_cur]->data, rx_len);
                    566:                        /* Add this packet to the receive queue. 
                    567:                         */
                    568:                        netdev_rx (netdev, rx_iob);
                    569:                }
                    570:                np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
                    571:                np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
                    572:                rx_status = np->rx[np->rx_cur].cmdsts; 
                    573:        }
                    574: end:
                    575:        /* re-enable the potentially idle receive state machine 
                    576:         */
                    577:        outl (RxOn, np->ioaddr + ChipCmd);      
                    578: }                              
                    579: 
                    580: /**
                    581:  * Enable/disable interrupts
                    582:  *
                    583:  * @v netdev    Network device
                    584:  * @v enable    Non-zero for enable, zero for disable
                    585:  */
                    586: static void natsemi_irq (struct net_device *netdev, int enable)
                    587: {
                    588:         struct natsemi_private *np = netdev->priv;
                    589: 
                    590:        outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
                    591:              np->ioaddr + IntrMask); 
                    592:        outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
                    593: }
                    594: 
                    595: static struct pci_device_id natsemi_nics[] = {
                    596:        PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815", 0),
                    597: };
                    598: 
                    599: struct pci_driver natsemi_driver __pci_driver = {
                    600:        .ids = natsemi_nics,
                    601:        .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
                    602:        .probe = natsemi_probe,
                    603:        .remove = natsemi_remove,
                    604: };

unix.superglobalmegacorp.com

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