Annotation of Gnu-Mach/linux/src/drivers/net/pcnet32.c, revision 1.1

1.1     ! root        1: /* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */
        !             2: /*
        !             3:  *  Copyright 1996,97 Thomas Bogendoerfer, 1993-1995,1998 Donald Becker
        !             4:  *     Copyright 1993 United States Government as represented by the
        !             5:  *     Director, National Security Agency.
        !             6:  *
        !             7:  *     Derived from the lance driver written 1993-1995 by Donald Becker.
        !             8:  *
        !             9:  *     This software may be used and distributed according to the terms
        !            10:  *     of the GNU Public License, incorporated herein by reference.
        !            11:  *
        !            12:  *     This driver is for AMD PCnet-PCI based ethercards
        !            13:  */
        !            14: 
        !            15: static const char *version = "pcnet32.c:v0.99B 4/4/98 DJBecker/TSBogend.\n";
        !            16: 
        !            17: /* A few user-configurable values. */
        !            18: 
        !            19: /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
        !            20: static int max_interrupt_work = 20;
        !            21: 
        !            22: /*
        !            23:  * Set the number of Tx and Rx buffers, using Log_2(# buffers).
        !            24:  * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
        !            25:  * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
        !            26:  */
        !            27: #define PCNET_LOG_TX_BUFFERS 4
        !            28: #define PCNET_LOG_RX_BUFFERS 4
        !            29: 
        !            30: #ifdef MODULE
        !            31: #ifdef MODVERSIONS
        !            32: #include <linux/modversions.h>
        !            33: #endif
        !            34: #include <linux/module.h>
        !            35: #include <linux/version.h>
        !            36: #else
        !            37: #define MOD_INC_USE_COUNT
        !            38: #define MOD_DEC_USE_COUNT
        !            39: #endif
        !            40: 
        !            41: #include <linux/kernel.h>
        !            42: #include <linux/sched.h>
        !            43: #include <linux/string.h>
        !            44: #include <linux/ptrace.h>
        !            45: #include <linux/errno.h>
        !            46: #include <linux/ioport.h>
        !            47: #include <linux/malloc.h>
        !            48: #include <linux/interrupt.h>
        !            49: #include <linux/pci.h>
        !            50: #include <linux/bios32.h>
        !            51: #include <asm/bitops.h>
        !            52: #include <asm/io.h>
        !            53: #include <asm/dma.h>
        !            54: 
        !            55: #include <linux/netdevice.h>
        !            56: #include <linux/etherdevice.h>
        !            57: #include <linux/skbuff.h>
        !            58: 
        !            59: /* Driver verbosity level.  0 = no messages, 7 = wordy death.
        !            60:    Modify here, or when loading as a module. */
        !            61: static int pcnet32_debug = 1;
        !            62: 
        !            63: /*
        !            64:  *                             Theory of Operation
        !            65:  *
        !            66:  * This driver uses the same software structure as the normal lance
        !            67:  * driver. So look for a verbose description in lance.c. The differences
        !            68:  * to the normal lance driver is the use of the 32bit mode of PCnet32
        !            69:  * and PCnetPCI chips. Because these chips are 32bit chips, there is no
        !            70:  * 16MB limitation and we don't need bounce buffers.
        !            71:  */
        !            72: 
        !            73: /*
        !            74:  * History:
        !            75:  * v0.01:  Initial version
        !            76:  *         only tested on Alpha Noname Board
        !            77:  * v0.02:  changed IRQ handling for new interrupt scheme (dev_id)
        !            78:  *         tested on a ASUS SP3G
        !            79:  * v0.10:  fixed an odd problem with the 79C794 in a Compaq Deskpro XL
        !            80:  *         looks like the 974 doesn't like stopping and restarting in a
        !            81:  *         short period of time; now we do a reinit of the lance; the
        !            82:  *         bug was triggered by doing ifconfig eth0 <ip> broadcast <addr>
        !            83:  *         and hangs the machine (thanks to Klaus Liedl for debugging)
        !            84:  * v0.12:  by suggestion from Donald Becker: Renamed driver to pcnet32,
        !            85:  *         made it standalone (no need for lance.c)
        !            86:  * v0.13:  added additional PCI detecting for special PCI devices (Compaq)
        !            87:  * v0.14:  stripped down additional PCI probe (thanks to David C Niemi
        !            88:  *         and [email protected] for testing this on their Compaq boxes)
        !            89:  * v0.15:  added 79C965 (VLB) probe
        !            90:  *         added interrupt sharing for PCI chips
        !            91:  * v0.16:  fixed set_multicast_list on Alpha machines
        !            92:  * v0.17:  removed hack from dev.c; now pcnet32 uses ethif_probe in Space.c
        !            93:  * v0.19:  changed setting of autoselect bit
        !            94:  * v0.20:  removed additional Compaq PCI probe; there is now a working one
        !            95:  *        in arch/i386/bios32.c
        !            96:  * v0.21:  added endian conversion for ppc, from work by [email protected]
        !            97:  * v0.22:  added printing of status to ring dump
        !            98:  * v0.23:  changed enet_statistics to net_devive_stats
        !            99:  * v0.99: Changes for 2.0.34 final release. -djb
        !           100:  */
        !           101: 
        !           102: 
        !           103: #ifndef __powerpc__
        !           104: #define le16_to_cpu(val)  (val)
        !           105: #define le32_to_cpu(val)  (val)
        !           106: #endif
        !           107: #if (LINUX_VERSION_CODE < 0x20123)
        !           108: #define test_and_set_bit(val, addr) set_bit(val, addr)
        !           109: #endif
        !           110: 
        !           111: #define TX_RING_SIZE                   (1 << (PCNET_LOG_TX_BUFFERS))
        !           112: #define TX_RING_MOD_MASK               (TX_RING_SIZE - 1)
        !           113: #define TX_RING_LEN_BITS               ((PCNET_LOG_TX_BUFFERS) << 12)
        !           114: 
        !           115: #define RX_RING_SIZE                   (1 << (PCNET_LOG_RX_BUFFERS))
        !           116: #define RX_RING_MOD_MASK               (RX_RING_SIZE - 1)
        !           117: #define RX_RING_LEN_BITS               ((PCNET_LOG_RX_BUFFERS) << 4)
        !           118: 
        !           119: #define PKT_BUF_SZ             1544
        !           120: 
        !           121: /* Offsets from base I/O address. */
        !           122: enum pcnet_offsets { PCNET32_DATA=0x10, PCNET32_ADDR=0x12, PCNET32_RESET=0x14,
        !           123:                                         PCNET32_BUS_IF=0x16,};
        !           124: #define PCNET32_TOTAL_SIZE 0x20
        !           125: 
        !           126: /* The PCNET32 Rx and Tx ring descriptors. */
        !           127: struct pcnet32_rx_head {
        !           128:        u32 base;
        !           129:        s16 buf_length;
        !           130:        s16 status;
        !           131:        u32 msg_length;
        !           132:        u32 reserved;
        !           133: };
        !           134: 
        !           135: struct pcnet32_tx_head {
        !           136:        u32 base;
        !           137:        s16 length;
        !           138:        s16 status;
        !           139:        u32 misc;
        !           140:        u32 reserved;
        !           141: };
        !           142: 
        !           143: /* The PCNET32 32-Bit initialization block, described in databook. */
        !           144: struct pcnet32_init_block {
        !           145:        u16 mode;
        !           146:        u16 tlen_rlen;
        !           147:        u8  phys_addr[6];
        !           148:        u16 reserved;
        !           149:        u32 filter[2];
        !           150:        /* Receive and transmit ring base, along with extra bits. */
        !           151:        u32 rx_ring;
        !           152:        u32 tx_ring;
        !           153: };
        !           154: 
        !           155: struct pcnet32_private {
        !           156:        /* The Tx and Rx ring entries must be aligned on 16-byte boundaries
        !           157:           in 32bit mode. */
        !           158:        struct pcnet32_rx_head   rx_ring[RX_RING_SIZE];
        !           159:        struct pcnet32_tx_head   tx_ring[TX_RING_SIZE];
        !           160:        struct pcnet32_init_block       init_block;
        !           161:        const char *name;
        !           162:        struct device *next_module;
        !           163:        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        !           164:        struct sk_buff* tx_skbuff[TX_RING_SIZE];
        !           165:        unsigned long rx_buffs;         /* Address of Rx and Tx buffers. */
        !           166:        int cur_rx, cur_tx;                     /* The next free ring entry */
        !           167:        int dirty_rx, dirty_tx;         /* The ring entries to be free()ed. */
        !           168:        struct enet_statistics stats;
        !           169:        char tx_full;
        !           170:        unsigned long lock;
        !           171: };
        !           172: 
        !           173: static struct pcnet_chip_type {
        !           174:        int id_number;
        !           175:        const char *name;
        !           176:        int flags;
        !           177: } chip_table[] = {
        !           178:        {0x2420, "PCnet/PCI 79C970", 0},
        !           179:        {0x2430, "PCnet32", 0},
        !           180:        {0x2621, "PCnet/PCI II 79C970A", 0},
        !           181:        {0x2623, "PCnet/FAST 79C971", 0},
        !           182:        {0x2624, "PCnet/FAST+ 79C972", 0},
        !           183:        {0x0,    "PCnet32 (unknown)", 0},
        !           184: };
        !           185: 
        !           186: /* Index of functions. */
        !           187: int  pcnet32_probe(struct device *dev);
        !           188: static int  pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line);
        !           189: static int  pcnet32_open(struct device *dev);
        !           190: static void pcnet32_init_ring(struct device *dev);
        !           191: static int  pcnet32_start_xmit(struct sk_buff *skb, struct device *dev);
        !           192: static int  pcnet32_rx(struct device *dev);
        !           193: static void pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           194: static int  pcnet32_close(struct device *dev);
        !           195: static struct enet_statistics *pcnet32_get_stats(struct device *dev);
        !           196: static void pcnet32_set_multicast_list(struct device *dev);
        !           197: 
        !           198: 
        !           199: /* A list of all installed PCnet32 devices, for removing the driver module. */
        !           200: static struct device *root_pcnet32_dev = NULL;
        !           201: 
        !           202: int pcnet32_probe (struct device *dev)
        !           203: {
        !           204:        static int pci_index = 0;       /* Static, for multiple probe calls. */
        !           205:        int cards_found = 0;
        !           206: 
        !           207:        if ( ! pcibios_present())
        !           208:                return ENODEV;
        !           209: 
        !           210:        for (;pci_index < 0xff; pci_index++) {
        !           211:                u8 irq_line;
        !           212:                u16 pci_command, new_command;
        !           213:                unsigned char pci_bus, pci_device_fn;
        !           214:                u32 pci_ioaddr;
        !           215: 
        !           216:                if (pcibios_find_device (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
        !           217:                                                                 pci_index, &pci_bus, &pci_device_fn)
        !           218:                        != PCIBIOS_SUCCESSFUL)
        !           219:                        break;
        !           220: 
        !           221:                pcibios_read_config_byte(pci_bus, pci_device_fn,
        !           222:                                                                 PCI_INTERRUPT_LINE, &irq_line);
        !           223:                pcibios_read_config_dword(pci_bus, pci_device_fn,
        !           224:                                                                  PCI_BASE_ADDRESS_0, &pci_ioaddr);
        !           225:                /* Remove I/O space marker in bit 0. */
        !           226:                pci_ioaddr &= ~3;
        !           227: 
        !           228:                /* Avoid already found cards from previous pcnet32_probe() calls */
        !           229:                if (check_region(pci_ioaddr, PCNET32_TOTAL_SIZE))
        !           230:                        continue;
        !           231: 
        !           232:                /* Activate the card: fix for brain-damaged Win98 BIOSes. */
        !           233:                pcibios_read_config_word(pci_bus, pci_device_fn,
        !           234:                                                                 PCI_COMMAND, &pci_command);
        !           235:                new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
        !           236:                if (pci_command != new_command) {
        !           237:                        printk(KERN_INFO "  The PCI BIOS has not enabled the AMD Ethernet"
        !           238:                                   " device at %2x-%2x."
        !           239:                                   "  Updating PCI command %4.4x->%4.4x.\n",
        !           240:                                   pci_bus, pci_device_fn, pci_command, new_command);
        !           241:                        pcibios_write_config_word(pci_bus, pci_device_fn,
        !           242:                                                                          PCI_COMMAND, new_command);
        !           243:                }
        !           244: 
        !           245:                if (pcnet32_probe1(dev, pci_ioaddr, irq_line) != 0) {
        !           246:                        /* Should never happen. */
        !           247:                        printk(KERN_ERR "pcnet32.c: Probe of PCI card at %#x failed.\n",
        !           248:                                   pci_ioaddr);
        !           249:                } else
        !           250:                        dev = 0;
        !           251:                cards_found++;
        !           252:        }
        !           253: 
        !           254:        return cards_found ? 0 : -ENODEV;
        !           255: }
        !           256: 
        !           257: 
        !           258: /* pcnet32_probe1 */
        !           259: static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line)
        !           260: {
        !           261:        struct pcnet32_private *lp;
        !           262:        int i;
        !           263:        const char *chipname;
        !           264: 
        !           265:        /* check if there is really a pcnet chip on that ioaddr */
        !           266:        if ((inb(ioaddr + 14) != 0x57) || (inb(ioaddr + 15) != 0x57))
        !           267:                return ENODEV;
        !           268: 
        !           269:        inw(ioaddr+PCNET32_RESET); /* Reset the PCNET32 */
        !           270: 
        !           271:        outw(0x0000, ioaddr+PCNET32_ADDR); /* Switch to window 0 */
        !           272:        if (inw(ioaddr+PCNET32_DATA) != 0x0004)
        !           273:                return ENODEV;
        !           274: 
        !           275:        /* Get the version of the chip. */
        !           276:        outw(88, ioaddr+PCNET32_ADDR);
        !           277:        if (inw(ioaddr+PCNET32_ADDR) != 88) {
        !           278:                /* should never happen */
        !           279:                return ENODEV;
        !           280:        } else {                        /* Good, it's a newer chip. */
        !           281:                int chip_version = inw(ioaddr+PCNET32_DATA);
        !           282:                outw(89, ioaddr+PCNET32_ADDR);
        !           283:                chip_version |= inw(ioaddr+PCNET32_DATA) << 16;
        !           284:                if (pcnet32_debug > 2)
        !           285:                        printk("  PCnet chip version is %#x.\n", chip_version);
        !           286:                if ((chip_version & 0xfff) != 0x003)
        !           287:                        return ENODEV;
        !           288:                chip_version = (chip_version >> 12) & 0xffff;
        !           289:                for (i = 0; chip_table[i].id_number; i++)
        !           290:                        if (chip_table[i].id_number == chip_version)
        !           291:                                break;
        !           292:                chipname = chip_table[i].name;
        !           293:        }
        !           294: 
        !           295:        dev = init_etherdev(dev, 0);
        !           296: 
        !           297:        printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
        !           298: 
        !           299:        /* There is a 16 byte station address PROM at the base address.
        !           300:           The first six bytes are the station address. */
        !           301:        for (i = 0; i < 6; i++)
        !           302:                printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
        !           303:                
        !           304:        printk("\n");
        !           305: 
        !           306:        dev->base_addr = ioaddr;
        !           307:        request_region(ioaddr, PCNET32_TOTAL_SIZE, dev->name);
        !           308: 
        !           309:        /* Data structures used by the PCnet32 are 16byte aligned and DMAble. */
        !           310:     lp = (struct pcnet32_private *)
        !           311:                (((unsigned long)kmalloc(sizeof(*lp)+15, GFP_DMA | GFP_KERNEL)+15) & ~15);
        !           312: 
        !           313:     memset(lp, 0, sizeof(*lp));
        !           314:        dev->priv = lp;
        !           315: 
        !           316:        lp->next_module = root_pcnet32_dev;
        !           317:        root_pcnet32_dev = dev;
        !           318: 
        !           319:     lp->name = chipname;
        !           320:     lp->rx_buffs = (unsigned long) kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL);
        !           321: 
        !           322:     lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
        !           323:     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
        !           324:     for (i = 0; i < 6; i++)
        !           325:       lp->init_block.phys_addr[i] = dev->dev_addr[i];
        !           326:     lp->init_block.filter[0] = 0x00000000;
        !           327:     lp->init_block.filter[1] = 0x00000000;
        !           328:     lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring));
        !           329:     lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring));
        !           330: 
        !           331:     /* switch pcnet32 to 32bit mode */
        !           332:     outw(0x0014, ioaddr+PCNET32_ADDR);
        !           333:     outw(0x0002, ioaddr+PCNET32_BUS_IF);
        !           334: 
        !           335:     outw(0x0001, ioaddr+PCNET32_ADDR);
        !           336:     inw(ioaddr+PCNET32_ADDR);
        !           337:     outw(virt_to_bus(&lp->init_block) & 0xffff, ioaddr+PCNET32_DATA);
        !           338:     outw(0x0002, ioaddr+PCNET32_ADDR);
        !           339:     inw(ioaddr+PCNET32_ADDR);
        !           340:     outw(virt_to_bus(&lp->init_block) >> 16, ioaddr+PCNET32_DATA);
        !           341:     outw(0x0000, ioaddr+PCNET32_ADDR);
        !           342:     inw(ioaddr+PCNET32_ADDR);
        !           343: 
        !           344:     dev->irq = irq_line;
        !           345: 
        !           346:     if (pcnet32_debug > 0)
        !           347:       printk(version);
        !           348: 
        !           349:     /* The PCNET32-specific entries in the device structure. */
        !           350:     dev->open = &pcnet32_open;
        !           351:     dev->hard_start_xmit = &pcnet32_start_xmit;
        !           352:     dev->stop = &pcnet32_close;
        !           353:     dev->get_stats = &pcnet32_get_stats;
        !           354:     dev->set_multicast_list = &pcnet32_set_multicast_list;
        !           355: 
        !           356:     /* Fill in the generic fields of the device structure. */
        !           357:     ether_setup(dev);
        !           358:     return 0;
        !           359: }
        !           360: 
        !           361: 
        !           362: static int
        !           363: pcnet32_open(struct device *dev)
        !           364: {
        !           365:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           366:        unsigned int ioaddr = dev->base_addr;
        !           367:        int i;
        !           368: 
        !           369:        if (dev->irq == 0 ||
        !           370:                request_irq(dev->irq, &pcnet32_interrupt, SA_SHIRQ,
        !           371:                                        dev->name, (void *)dev)) {
        !           372:                return -EAGAIN;
        !           373:        }
        !           374:        MOD_INC_USE_COUNT;
        !           375: 
        !           376:        /* Reset the PCNET32 */
        !           377:        inw(ioaddr+PCNET32_RESET);
        !           378: 
        !           379:        /* switch pcnet32 to 32bit mode */
        !           380:        outw(0x0014, ioaddr+PCNET32_ADDR);
        !           381:        outw(0x0002, ioaddr+PCNET32_BUS_IF);
        !           382: 
        !           383:        /* Turn on auto-select of media (AUI, BNC). */
        !           384:        outw(0x0002, ioaddr+PCNET32_ADDR);
        !           385:        /* only touch autoselect bit */
        !           386:        outw(inw(ioaddr+PCNET32_BUS_IF) | 0x0002, ioaddr+PCNET32_BUS_IF);
        !           387: 
        !           388:        if (pcnet32_debug > 1)
        !           389:                printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
        !           390:                           dev->name, dev->irq,
        !           391:                           (u32) virt_to_bus(lp->tx_ring),
        !           392:                           (u32) virt_to_bus(lp->rx_ring),
        !           393:                           (u32) virt_to_bus(&lp->init_block));
        !           394: 
        !           395:        /* check for ATLAS T1/E1 LAW card */
        !           396:        if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75) {
        !           397:                /* select GPSI mode */
        !           398:                lp->init_block.mode = 0x0100;
        !           399:                outw(0x0002, ioaddr+PCNET32_ADDR);
        !           400:                outw(inw(ioaddr+PCNET32_BUS_IF) & ~2, ioaddr+PCNET32_BUS_IF);
        !           401:                /* switch full duplex on */
        !           402:                outw(0x0009, ioaddr+PCNET32_ADDR);
        !           403:                outw(inw(ioaddr+PCNET32_BUS_IF) | 1, ioaddr+PCNET32_BUS_IF);
        !           404:        } else
        !           405:                lp->init_block.mode = 0x0000;
        !           406:        lp->init_block.filter[0] = 0x00000000;
        !           407:        lp->init_block.filter[1] = 0x00000000;
        !           408:        pcnet32_init_ring(dev);
        !           409: 
        !           410:        /* Re-initialize the PCNET32, and start it when done. */
        !           411:        outw(0x0001, ioaddr+PCNET32_ADDR);
        !           412:        outw(virt_to_bus(&lp->init_block) &0xffff, ioaddr+PCNET32_DATA);
        !           413:        outw(0x0002, ioaddr+PCNET32_ADDR);
        !           414:        outw(virt_to_bus(&lp->init_block) >> 16, ioaddr+PCNET32_DATA);
        !           415: 
        !           416:        outw(0x0004, ioaddr+PCNET32_ADDR);
        !           417:        outw(0x0915, ioaddr+PCNET32_DATA);
        !           418: 
        !           419:        outw(0x0000, ioaddr+PCNET32_ADDR);
        !           420:        outw(0x0001, ioaddr+PCNET32_DATA);
        !           421: 
        !           422:        dev->tbusy = 0;
        !           423:        dev->interrupt = 0;
        !           424:        dev->start = 1;
        !           425:        i = 0;
        !           426:        while (i++ < 100)
        !           427:                if (inw(ioaddr+PCNET32_DATA) & 0x0100)
        !           428:                        break;
        !           429:        /*
        !           430:         * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
        !           431:         * reports that doing so triggers a bug in the '974.
        !           432:         */
        !           433:        outw(0x0042, ioaddr+PCNET32_DATA);
        !           434: 
        !           435:        if (pcnet32_debug > 2)
        !           436:                printk("%s: PCNET32 open after %d ticks, init block %#x csr0 %4.4x.\n",
        !           437:                           dev->name, i, (u32) virt_to_bus(&lp->init_block), inw(ioaddr+PCNET32_DATA));
        !           438: 
        !           439:        return 0;                                       /* Always succeed */
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * The LANCE has been halted for one reason or another (busmaster memory
        !           444:  * arbitration error, Tx FIFO underflow, driver stopped it to reconfigure,
        !           445:  * etc.).  Modern LANCE variants always reload their ring-buffer
        !           446:  * configuration when restarted, so we must reinitialize our ring
        !           447:  * context before restarting.  As part of this reinitialization,
        !           448:  * find all packets still on the Tx ring and pretend that they had been
        !           449:  * sent (in effect, drop the packets on the floor) - the higher-level
        !           450:  * protocols will time out and retransmit.  It'd be better to shuffle
        !           451:  * these skbs to a temp list and then actually re-Tx them after
        !           452:  * restarting the chip, but I'm too lazy to do so right now.  [email protected]
        !           453:  */
        !           454: 
        !           455: static void
        !           456: pcnet32_purge_tx_ring(struct device *dev)
        !           457: {
        !           458:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           459:        int i;
        !           460: 
        !           461:        for (i = 0; i < TX_RING_SIZE; i++) {
        !           462:                if (lp->tx_skbuff[i]) {
        !           463:                        dev_kfree_skb(lp->tx_skbuff[i], FREE_WRITE);
        !           464:                        lp->tx_skbuff[i] = NULL;
        !           465:                }
        !           466:        }
        !           467: }
        !           468: 
        !           469: 
        !           470: /* Initialize the PCNET32 Rx and Tx rings. */
        !           471: static void
        !           472: pcnet32_init_ring(struct device *dev)
        !           473: {
        !           474:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           475:        int i;
        !           476: 
        !           477:        lp->lock = 0, lp->tx_full = 0;
        !           478:        lp->cur_rx = lp->cur_tx = 0;
        !           479:        lp->dirty_rx = lp->dirty_tx = 0;
        !           480: 
        !           481:        for (i = 0; i < RX_RING_SIZE; i++) {
        !           482:                lp->rx_ring[i].base = (u32)le32_to_cpu(virt_to_bus((char *)lp->rx_buffs + i*PKT_BUF_SZ));
        !           483:                lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ);
        !           484:                lp->rx_ring[i].status = le16_to_cpu(0x8000);
        !           485:        }
        !           486:        /* The Tx buffer address is filled in as needed, but we do need to clear
        !           487:           the upper ownership bit. */
        !           488:        for (i = 0; i < TX_RING_SIZE; i++) {
        !           489:                lp->tx_ring[i].base = 0;
        !           490:                lp->tx_ring[i].status = 0;
        !           491:        }
        !           492: 
        !           493:        lp->init_block.tlen_rlen = TX_RING_LEN_BITS | RX_RING_LEN_BITS;
        !           494:        for (i = 0; i < 6; i++)
        !           495:                lp->init_block.phys_addr[i] = dev->dev_addr[i];
        !           496:        lp->init_block.rx_ring = (u32)le32_to_cpu(virt_to_bus(lp->rx_ring));
        !           497:        lp->init_block.tx_ring = (u32)le32_to_cpu(virt_to_bus(lp->tx_ring));
        !           498: }
        !           499: 
        !           500: static void
        !           501: pcnet32_restart(struct device *dev, unsigned int csr0_bits, int must_reinit)
        !           502: {
        !           503:         int i;
        !           504:        unsigned int ioaddr = dev->base_addr;
        !           505: 
        !           506:        pcnet32_purge_tx_ring(dev);
        !           507:        pcnet32_init_ring(dev);
        !           508: 
        !           509:        outw(0x0000, ioaddr + PCNET32_ADDR);
        !           510:         /* ReInit Ring */
        !           511:         outw(0x0001, ioaddr + PCNET32_DATA);
        !           512:        i = 0;
        !           513:        while (i++ < 100)
        !           514:                if (inw(ioaddr+PCNET32_DATA) & 0x0100)
        !           515:                        break;
        !           516: 
        !           517:        outw(csr0_bits, ioaddr + PCNET32_DATA);
        !           518: }
        !           519: 
        !           520: static int
        !           521: pcnet32_start_xmit(struct sk_buff *skb, struct device *dev)
        !           522: {
        !           523:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           524:        unsigned int ioaddr = dev->base_addr;
        !           525:        int entry;
        !           526:        unsigned long flags;
        !           527: 
        !           528:        /* Transmitter timeout, serious problems. */
        !           529:        if (dev->tbusy) {
        !           530:                int tickssofar = jiffies - dev->trans_start;
        !           531:                if (tickssofar < 20)
        !           532:                        return 1;
        !           533:                outw(0, ioaddr+PCNET32_ADDR);
        !           534:                printk("%s: transmit timed out, status %4.4x, resetting.\n",
        !           535:                           dev->name, inw(ioaddr+PCNET32_DATA));
        !           536:                outw(0x0004, ioaddr+PCNET32_DATA);
        !           537:                lp->stats.tx_errors++;
        !           538: #ifndef final_version
        !           539:                {
        !           540:                        int i;
        !           541:                        printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
        !           542:                                   lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
        !           543:                                   lp->cur_rx);
        !           544:                        for (i = 0 ; i < RX_RING_SIZE; i++)
        !           545:                                printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
        !           546:                                           lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
        !           547:                                           lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status);
        !           548:                        for (i = 0 ; i < TX_RING_SIZE; i++)
        !           549:                                printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
        !           550:                                           lp->tx_ring[i].base, -lp->tx_ring[i].length,
        !           551:                                           lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status);
        !           552:                        printk("\n");
        !           553:                }
        !           554: #endif
        !           555:                pcnet32_restart(dev, 0x0042, 1);
        !           556: 
        !           557:                dev->tbusy = 0;
        !           558:                dev->trans_start = jiffies;
        !           559: 
        !           560:                return 0;
        !           561:        }
        !           562: 
        !           563:        if (pcnet32_debug > 3) {
        !           564:                outw(0x0000, ioaddr+PCNET32_ADDR);
        !           565:                printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name,
        !           566:                           inw(ioaddr+PCNET32_DATA));
        !           567:                outw(0x0000, ioaddr+PCNET32_DATA);
        !           568:        }
        !           569: 
        !           570:        /* Block a timer-based transmit from overlapping.  This could better be
        !           571:           done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
        !           572:        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
        !           573:                printk("%s: Transmitter access conflict.\n", dev->name);
        !           574:                return 1;
        !           575:        }
        !           576: 
        !           577:        if (test_and_set_bit(0, (void*)&lp->lock) != 0) {
        !           578:                if (pcnet32_debug > 0)
        !           579:                        printk("%s: tx queue lock!.\n", dev->name);
        !           580:                /* don't clear dev->tbusy flag. */
        !           581:                return 1;
        !           582:        }
        !           583: 
        !           584:        /* Fill in a Tx ring entry */
        !           585: 
        !           586:        /* Mask to ring buffer boundary. */
        !           587:        entry = lp->cur_tx & TX_RING_MOD_MASK;
        !           588: 
        !           589:        /* Caution: the write order is important here, set the base address
        !           590:           with the "ownership" bits last. */
        !           591: 
        !           592:        lp->tx_ring[entry].length = le16_to_cpu(-skb->len);
        !           593: 
        !           594:        lp->tx_ring[entry].misc = 0x00000000;
        !           595: 
        !           596:        lp->tx_skbuff[entry] = skb;
        !           597:        lp->tx_ring[entry].base = (u32)le32_to_cpu(virt_to_bus(skb->data));
        !           598:        lp->tx_ring[entry].status = le16_to_cpu(0x8300);
        !           599: 
        !           600:        lp->cur_tx++;
        !           601: 
        !           602:        /* Trigger an immediate send poll. */
        !           603:        outw(0x0000, ioaddr+PCNET32_ADDR);
        !           604:        outw(0x0048, ioaddr+PCNET32_DATA);
        !           605: 
        !           606:        dev->trans_start = jiffies;
        !           607: 
        !           608:        save_flags(flags);
        !           609:        cli();
        !           610:        lp->lock = 0;
        !           611:        if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
        !           612:                clear_bit(0, (void*)&dev->tbusy);
        !           613:        else
        !           614:                lp->tx_full = 1;
        !           615:        restore_flags(flags);
        !           616: 
        !           617:        return 0;
        !           618: }
        !           619: 
        !           620: /* The PCNET32 interrupt handler. */
        !           621: static void
        !           622: pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        !           623: {
        !           624:        struct device *dev = (struct device *)dev_id;
        !           625:        struct pcnet32_private *lp;
        !           626:        unsigned int csr0, ioaddr;
        !           627:        int boguscnt = max_interrupt_work;
        !           628:        int must_restart;
        !           629: 
        !           630:        if (dev == NULL) {
        !           631:                printk ("pcnet32_interrupt(): irq %d for unknown device.\n", irq);
        !           632:                return;
        !           633:        }
        !           634: 
        !           635:        ioaddr = dev->base_addr;
        !           636:        lp = (struct pcnet32_private *)dev->priv;
        !           637:        if (dev->interrupt)
        !           638:                printk("%s: Re-entering the interrupt handler.\n", dev->name);
        !           639: 
        !           640:        dev->interrupt = 1;
        !           641: 
        !           642:        outw(0x00, dev->base_addr + PCNET32_ADDR);
        !           643:        while ((csr0 = inw(dev->base_addr + PCNET32_DATA)) & 0x8600
        !           644:                   && --boguscnt >= 0) {
        !           645:                /* Acknowledge all of the current interrupt sources ASAP. */
        !           646:                outw(csr0 & ~0x004f, dev->base_addr + PCNET32_DATA);
        !           647: 
        !           648:                must_restart = 0;
        !           649: 
        !           650:                if (pcnet32_debug > 5)
        !           651:                        printk("%s: interrupt  csr0=%#2.2x new csr=%#2.2x.\n",
        !           652:                                   dev->name, csr0, inw(dev->base_addr + PCNET32_DATA));
        !           653: 
        !           654:                if (csr0 & 0x0400)                      /* Rx interrupt */
        !           655:                        pcnet32_rx(dev);
        !           656: 
        !           657:                if (csr0 & 0x0200) {            /* Tx-done interrupt */
        !           658:                        int dirty_tx = lp->dirty_tx;
        !           659: 
        !           660:                        while (dirty_tx < lp->cur_tx) {
        !           661:                                int entry = dirty_tx & TX_RING_MOD_MASK;
        !           662:                                int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
        !           663: 
        !           664:                                if (status < 0)
        !           665:                                        break;                  /* It still hasn't been Txed */
        !           666: 
        !           667:                                lp->tx_ring[entry].base = 0;
        !           668: 
        !           669:                                if (status & 0x4000) {
        !           670:                                        /* There was an major error, log it. */
        !           671:                                        int err_status = le16_to_cpu(lp->tx_ring[entry].misc);
        !           672:                                        lp->stats.tx_errors++;
        !           673:                                        if (err_status & 0x04000000) lp->stats.tx_aborted_errors++;
        !           674:                                        if (err_status & 0x08000000) lp->stats.tx_carrier_errors++;
        !           675:                                        if (err_status & 0x10000000) lp->stats.tx_window_errors++;
        !           676:                                        if (err_status & 0x40000000) {
        !           677:                                                /* Ackk!  On FIFO errors the Tx unit is turned off! */
        !           678:                                                lp->stats.tx_fifo_errors++;
        !           679:                                                /* Remove this verbosity later! */
        !           680:                                                printk("%s: Tx FIFO error! Status %4.4x.\n",
        !           681:                                                           dev->name, csr0);
        !           682:                                                /* Restart the chip. */
        !           683:                                                must_restart = 1;
        !           684:                                        }
        !           685:                                } else {
        !           686:                                        if (status & 0x1800)
        !           687:                                                lp->stats.collisions++;
        !           688:                                        lp->stats.tx_packets++;
        !           689:                                }
        !           690: 
        !           691:                                /* We must free the original skb */
        !           692:                                if (lp->tx_skbuff[entry]) {
        !           693:                                        dev_kfree_skb(lp->tx_skbuff[entry], FREE_WRITE);
        !           694:                                        lp->tx_skbuff[entry] = 0;
        !           695:                                }
        !           696:                                dirty_tx++;
        !           697:                        }
        !           698: 
        !           699: #ifndef final_version
        !           700:                        if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
        !           701:                                printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
        !           702:                                           dirty_tx, lp->cur_tx, lp->tx_full);
        !           703:                                dirty_tx += TX_RING_SIZE;
        !           704:                        }
        !           705: #endif
        !           706: 
        !           707:                        if (lp->tx_full && dev->tbusy
        !           708:                                && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
        !           709:                                /* The ring is no longer full, clear tbusy. */
        !           710:                                lp->tx_full = 0;
        !           711:                                clear_bit(0, (void*)&dev->tbusy);
        !           712:                                mark_bh(NET_BH);
        !           713:                        }
        !           714: 
        !           715:                        lp->dirty_tx = dirty_tx;
        !           716:                }
        !           717: 
        !           718:                /* Log misc errors. */
        !           719:                if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */
        !           720:                if (csr0 & 0x1000) {
        !           721:                        /*
        !           722:                         * this happens when our receive ring is full. This 
        !           723:                         * shouldn't be a problem as we will see normal rx 
        !           724:                         * interrupts for the frames in the receive ring. But 
        !           725:                         * there are some PCI chipsets (I can reproduce this 
        !           726:                         * on SP3G with Intel saturn chipset) which have some-
        !           727:                         * times problems and will fill up the receive ring 
        !           728:                         * with error descriptors. In this situation we don't 
        !           729:                         * get a rx interrupt, but a missed frame interrupt 
        !           730:                         * sooner or later. So we try to clean up our receive 
        !           731:                         * ring here.
        !           732:                         */
        !           733:                        pcnet32_rx(dev);
        !           734:                        lp->stats.rx_errors++; /* Missed a Rx frame. */
        !           735:                }
        !           736:                if (csr0 & 0x0800) {
        !           737:                        printk("%s: Bus master arbitration failure, status %4.4x.\n",
        !           738:                                   dev->name, csr0);
        !           739:                        /* Restart the chip. */
        !           740:                        must_restart = 1;
        !           741:                }
        !           742: 
        !           743:                if (must_restart) {
        !           744:                        /* stop the chip to clear the error condition, then restart */
        !           745:                        outw(0x0000, dev->base_addr + PCNET32_ADDR);
        !           746:                        outw(0x0004, dev->base_addr + PCNET32_DATA);
        !           747:                        pcnet32_restart(dev, 0x0002, 0);
        !           748:                }
        !           749:        }
        !           750: 
        !           751:        /* Clear any other interrupt, and set interrupt enable. */
        !           752:        outw(0x0000, dev->base_addr + PCNET32_ADDR);
        !           753:        outw(0x7940, dev->base_addr + PCNET32_DATA);
        !           754: 
        !           755:        if (pcnet32_debug > 4)
        !           756:                printk("%s: exiting interrupt, csr%d=%#4.4x.\n",
        !           757:                           dev->name, inw(ioaddr + PCNET32_ADDR),
        !           758:                           inw(dev->base_addr + PCNET32_DATA));
        !           759: 
        !           760:        dev->interrupt = 0;
        !           761:        return;
        !           762: }
        !           763: 
        !           764: static int
        !           765: pcnet32_rx(struct device *dev)
        !           766: {
        !           767:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           768:        int entry = lp->cur_rx & RX_RING_MOD_MASK;
        !           769:        int i;
        !           770: 
        !           771:        /* If we own the next entry, it's a new packet. Send it up. */
        !           772:        while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
        !           773:                int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8;
        !           774: 
        !           775:                if (status != 0x03) {                   /* There was an error. */
        !           776:                        /* There is a tricky error noted by John Murphy,
        !           777:                           <[email protected]> to Russ Nelson: Even with full-sized
        !           778:                           buffers it's possible for a jabber packet to use two
        !           779:                           buffers, with only the last correctly noting the error. */
        !           780:                        if (status & 0x01)      /* Only count a general error at the */
        !           781:                                lp->stats.rx_errors++; /* end of a packet.*/
        !           782:                        if (status & 0x20) lp->stats.rx_frame_errors++;
        !           783:                        if (status & 0x10) lp->stats.rx_over_errors++;
        !           784:                        if (status & 0x08) lp->stats.rx_crc_errors++;
        !           785:                        if (status & 0x04) lp->stats.rx_fifo_errors++;
        !           786:                        lp->rx_ring[entry].status &= le16_to_cpu(0x03ff);
        !           787:                }
        !           788:                else
        !           789:                {
        !           790:                        /* Malloc up new buffer, compatible with net-2e. */
        !           791:                        short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4;
        !           792:                        struct sk_buff *skb;
        !           793: 
        !           794:                        if(pkt_len < 60) {
        !           795:                                printk("%s: Runt packet!\n",dev->name);
        !           796:                                lp->stats.rx_errors++;
        !           797:                        } else {
        !           798:                                skb = dev_alloc_skb(pkt_len+2);
        !           799:                                if (skb == NULL) {
        !           800:                                        printk("%s: Memory squeeze, deferring packet.\n",
        !           801:                                                   dev->name);
        !           802:                                        for (i=0; i < RX_RING_SIZE; i++)
        !           803:                                                if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0)
        !           804:                                                        break;
        !           805: 
        !           806:                                        if (i > RX_RING_SIZE -2)
        !           807:                                        {
        !           808:                                                lp->stats.rx_dropped++;
        !           809:                                                lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
        !           810:                                                lp->cur_rx++;
        !           811:                                        }
        !           812:                                        break;
        !           813:                                }
        !           814:                                skb->dev = dev;
        !           815:                                skb_reserve(skb,2);     /* 16 byte align */
        !           816:                                skb_put(skb,pkt_len);   /* Make room */
        !           817:                                eth_copy_and_sum(skb,
        !           818:                                        (unsigned char *)bus_to_virt(le32_to_cpu(lp->rx_ring[entry].base)),
        !           819:                                        pkt_len,0);
        !           820:                                skb->protocol=eth_type_trans(skb,dev);
        !           821:                                netif_rx(skb);
        !           822:                                lp->stats.rx_packets++;
        !           823:                        }
        !           824:                }
        !           825:                /* The docs say that the buffer length isn't touched, but Andrew Boyd
        !           826:                   of QNX reports that some revs of the 79C965 clear it. */
        !           827:                lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);
        !           828:                lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
        !           829:                entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
        !           830:        }
        !           831: 
        !           832:        /* We should check that at least two ring entries are free.      If not,
        !           833:           we should free one and mark stats->rx_dropped++. */
        !           834: 
        !           835:        return 0;
        !           836: }
        !           837: 
        !           838: static int
        !           839: pcnet32_close(struct device *dev)
        !           840: {
        !           841:        unsigned int ioaddr = dev->base_addr;
        !           842:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           843: 
        !           844:        dev->start = 0;
        !           845:        set_bit(0, (void*)&dev->tbusy);
        !           846: 
        !           847:        outw(112, ioaddr+PCNET32_ADDR);
        !           848:        lp->stats.rx_missed_errors = inw(ioaddr+PCNET32_DATA);
        !           849: 
        !           850:        outw(0, ioaddr+PCNET32_ADDR);
        !           851: 
        !           852:        if (pcnet32_debug > 1)
        !           853:                printk("%s: Shutting down ethercard, status was %2.2x.\n",
        !           854:                           dev->name, inw(ioaddr+PCNET32_DATA));
        !           855: 
        !           856:        /* We stop the PCNET32 here -- it occasionally polls
        !           857:           memory if we don't. */
        !           858:        outw(0x0004, ioaddr+PCNET32_DATA);
        !           859: 
        !           860:        free_irq(dev->irq, dev);
        !           861:        MOD_DEC_USE_COUNT;
        !           862: 
        !           863:        return 0;
        !           864: }
        !           865: 
        !           866: static struct enet_statistics *pcnet32_get_stats(struct device *dev)
        !           867: {
        !           868:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           869:        unsigned int ioaddr = dev->base_addr;
        !           870:        unsigned short saved_addr;
        !           871:        unsigned long flags;
        !           872: 
        !           873:        save_flags(flags);
        !           874:        cli();
        !           875:        saved_addr = inw(ioaddr+PCNET32_ADDR);
        !           876:        outw(112, ioaddr+PCNET32_ADDR);
        !           877:        lp->stats.rx_missed_errors = inw(ioaddr+PCNET32_DATA);
        !           878:        outw(saved_addr, ioaddr+PCNET32_ADDR);
        !           879:        restore_flags(flags);
        !           880: 
        !           881:        return &lp->stats;
        !           882: }
        !           883: 
        !           884: /* Set or clear the multicast filter for this adaptor.
        !           885:  */
        !           886: 
        !           887: static void pcnet32_set_multicast_list(struct device *dev)
        !           888: {
        !           889:        unsigned int ioaddr = dev->base_addr;
        !           890:        struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
        !           891: 
        !           892:        if (dev->flags&IFF_PROMISC) {
        !           893:                /* Log any net taps. */
        !           894:                printk("%s: Promiscuous mode enabled.\n", dev->name);
        !           895:                lp->init_block.mode |= 0x8000;
        !           896:        } else {
        !           897:                int num_addrs=dev->mc_count;
        !           898:                if(dev->flags&IFF_ALLMULTI)
        !           899:                        num_addrs=1;
        !           900:                /* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */
        !           901:                memset(lp->init_block.filter , (num_addrs == 0) ? 0 : -1, sizeof(lp->init_block.filter));
        !           902:                lp->init_block.mode &= ~0x8000;
        !           903:        }
        !           904: 
        !           905:        outw(0, ioaddr+PCNET32_ADDR);
        !           906:        outw(0x0004, ioaddr+PCNET32_DATA); /* Temporarily stop the lance. */
        !           907: 
        !           908:        pcnet32_restart(dev, 0x0042, 0); /*  Resume normal operation */
        !           909: 
        !           910: }
        !           911: 
        !           912: 
        !           913: #ifdef MODULE
        !           914: #if LINUX_VERSION_CODE > 0x20118
        !           915: MODULE_AUTHOR("Donald Becker <[email protected]>");
        !           916: MODULE_DESCRIPTION("AMD PCnet/PCI ethernet driver");
        !           917: MODULE_PARM(debug, "i");
        !           918: MODULE_PARM(max_interrupt_work, "i");
        !           919: MODULE_PARM(rx_copybreak, "i");
        !           920: MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
        !           921: MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
        !           922: #endif
        !           923: 
        !           924: /* An additional parameter that may be passed in... */
        !           925: static int debug = -1;
        !           926: 
        !           927: int
        !           928: init_module(void)
        !           929: {
        !           930:        if (debug >= 0)
        !           931:                pcnet32_debug = debug;
        !           932: 
        !           933: #ifdef CARDBUS
        !           934:        register_driver(&pcnet32_ops);
        !           935:        return 0;
        !           936: #else
        !           937:        return pcnet32_probe(NULL);
        !           938: #endif
        !           939: }
        !           940: 
        !           941: void
        !           942: cleanup_module(void)
        !           943: {
        !           944:        struct device *next_dev;
        !           945: 
        !           946: #ifdef CARDBUS
        !           947:        unregister_driver(&pcnet32_ops);
        !           948: #endif
        !           949: 
        !           950:        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        !           951:        while (root_pcnet32_dev) {
        !           952:                next_dev = ((struct pcnet32_private *)root_pcnet32_dev->priv)->next_module;
        !           953:                unregister_netdev(root_pcnet32_dev);
        !           954:                release_region(root_pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
        !           955:                kfree(root_pcnet32_dev);
        !           956:                root_pcnet32_dev = next_dev;
        !           957:        }
        !           958: }
        !           959: 
        !           960: #endif  /* MODULE */
        !           961: 
        !           962: 
        !           963: /*
        !           964:  * Local variables:
        !           965:  *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c pcnet32.c  `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
        !           966:  *  c-indent-level: 4
        !           967:  *  c-basic-offset: 4
        !           968:  *  tab-width: 4
        !           969:  * End:
        !           970:  */

unix.superglobalmegacorp.com

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