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

1.1     ! root        1: /* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
        !             2: /*
        !             3:        Written 1993-1998 by Donald Becker.
        !             4: 
        !             5:        Copyright 1994-1998 by Donald Becker.
        !             6:        Copyright 1993 United States Government as represented by the
        !             7:        Director, National Security Agency.      This software may be used and
        !             8:        distributed according to the terms of the GNU Public License,
        !             9:        incorporated herein by reference.
        !            10: 
        !            11:        This driver is for the 3Com EtherLinkIII series.
        !            12: 
        !            13:        The author may be reached as [email protected] or
        !            14:        C/O Center of Excellence in Space Data and Information Sciences
        !            15:                Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
        !            16: 
        !            17:        Known limitations:
        !            18:        Because of the way 3c509 ISA detection works it's difficult to predict
        !            19:        a priori which of several ISA-mode cards will be detected first.
        !            20: 
        !            21:        This driver does not use predictive interrupt mode, resulting in higher
        !            22:        packet latency but lower overhead.  If interrupts are disabled for an
        !            23:        unusually long time it could also result in missed packets, but in
        !            24:        practice this rarely happens.
        !            25: 
        !            26: 
        !            27:        FIXES:
        !            28:                Alan Cox:       Removed the 'Unexpected interrupt' bug.
        !            29:                Michael Meskes: Upgraded to Donald Becker's version 1.07.
        !            30:                Alan Cox:       Increased the eeprom delay. Regardless of 
        !            31:                                what the docs say some people definitely
        !            32:                                get problems with lower (but in card spec)
        !            33:                                delays
        !            34:                v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
        !            35:                                other cleanups.  -djb
        !            36:                v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
        !            37:                v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
        !            38:                v1.15 1/31/98 Faster recovery for Tx errors. -djb
        !            39:                v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
        !            40: */
        !            41: 
        !            42: static char *version = "3c509.c:1.16 2/3/98 [email protected]\n";
        !            43: /* A few values that may be tweaked. */
        !            44: 
        !            45: /* Time in jiffies before concluding the transmitter is hung. */
        !            46: #define TX_TIMEOUT  (400*HZ/1000)
        !            47: /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
        !            48: static int max_interrupt_work = 10;
        !            49: 
        !            50: #include <linux/module.h>
        !            51: 
        !            52: #include <linux/config.h>
        !            53: #include <linux/kernel.h>
        !            54: #include <linux/sched.h>
        !            55: #include <linux/string.h>
        !            56: #include <linux/interrupt.h>
        !            57: #include <linux/ptrace.h>
        !            58: #include <linux/errno.h>
        !            59: #include <linux/in.h>
        !            60: #include <linux/malloc.h>
        !            61: #include <linux/ioport.h>
        !            62: #include <linux/netdevice.h>
        !            63: #include <linux/etherdevice.h>
        !            64: #include <linux/skbuff.h>
        !            65: #include <linux/config.h>      /* for CONFIG_MCA */
        !            66: #include <linux/delay.h>       /* for udelay() */
        !            67: 
        !            68: #include <asm/bitops.h>
        !            69: #include <asm/io.h>
        !            70: 
        !            71: #ifdef EL3_DEBUG
        !            72: int el3_debug = EL3_DEBUG;
        !            73: #else
        !            74: int el3_debug = 2;
        !            75: #endif
        !            76: 
        !            77: /* To minimize the size of the driver source I only define operating
        !            78:    constants if they are used several times.  You'll need the manual
        !            79:    anyway if you want to understand driver details. */
        !            80: /* Offsets from base I/O address. */
        !            81: #define EL3_DATA 0x00
        !            82: #define EL3_CMD 0x0e
        !            83: #define EL3_STATUS 0x0e
        !            84: #define         EEPROM_READ 0x80
        !            85: 
        !            86: #define EL3_IO_EXTENT  16
        !            87: 
        !            88: #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
        !            89: 
        !            90: 
        !            91: /* The top five bits written to EL3_CMD are a command, the lower
        !            92:    11 bits are the parameter, if applicable. */
        !            93: enum c509cmd {
        !            94:        TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
        !            95:        RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
        !            96:        TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
        !            97:        FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
        !            98:        SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
        !            99:        SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
        !           100:        StatsDisable = 22<<11, StopCoax = 23<<11,};
        !           101: 
        !           102: enum c509status {
        !           103:        IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
        !           104:        TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
        !           105:        IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
        !           106: 
        !           107: /* The SetRxFilter command accepts the following classes: */
        !           108: enum RxFilter {
        !           109:        RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
        !           110: 
        !           111: /* Register window 1 offsets, the window used in normal operation. */
        !           112: #define TX_FIFO                0x00
        !           113: #define RX_FIFO                0x00
        !           114: #define RX_STATUS      0x08
        !           115: #define TX_STATUS      0x0B
        !           116: #define TX_FREE                0x0C            /* Remaining free bytes in Tx buffer. */
        !           117: 
        !           118: #define WN0_IRQ                0x08            /* Window 0: Set IRQ line in bits 12-15. */
        !           119: #define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
        !           120: #define  MEDIA_TP      0x00C0          /* Enable link beat and jabber for 10baseT. */
        !           121: 
        !           122: /*
        !           123:  * Must be a power of two (we use a binary and in the
        !           124:  * circular queue)
        !           125:  */
        !           126: #define SKB_QUEUE_SIZE 64
        !           127: 
        !           128: struct el3_private {
        !           129:        struct enet_statistics stats;
        !           130:        struct device *next_dev;
        !           131:        /* skb send-queue */
        !           132:        int head, size;
        !           133:        struct sk_buff *queue[SKB_QUEUE_SIZE];
        !           134: };
        !           135: static int id_port = 0x110;            /* Start with 0x110 to avoid new sound cards.*/
        !           136: static struct device *el3_root_dev = NULL;
        !           137: 
        !           138: static ushort id_read_eeprom(int index);
        !           139: static ushort read_eeprom(int ioaddr, int index);
        !           140: static int el3_open(struct device *dev);
        !           141: static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
        !           142: static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           143: static void update_stats(int addr, struct device *dev);
        !           144: static struct enet_statistics *el3_get_stats(struct device *dev);
        !           145: static int el3_rx(struct device *dev);
        !           146: static int el3_close(struct device *dev);
        !           147: static void set_multicast_list(struct device *dev);
        !           148: 
        !           149: 
        !           150: 
        !           151: int el3_probe(struct device *dev)
        !           152: {
        !           153:        short lrs_state = 0xff, i;
        !           154:        int ioaddr, irq, if_port;
        !           155:        u16 phys_addr[3];
        !           156:        static int current_tag = 0;
        !           157: 
        !           158:        /* First check all slots of the EISA bus.  The next slot address to
        !           159:           probe is kept in 'eisa_addr' to support multiple probe() calls. */
        !           160:        if (EISA_bus) {
        !           161:                static int eisa_addr = 0x1000;
        !           162:                while (eisa_addr < 0x9000) {
        !           163:                        ioaddr = eisa_addr;
        !           164:                        eisa_addr += 0x1000;
        !           165: 
        !           166:                        /* Check the standard EISA ID register for an encoded '3Com'. */
        !           167:                        if (inw(ioaddr + 0xC80) != 0x6d50)
        !           168:                                continue;
        !           169: 
        !           170:                        /* Change the register set to the configuration window 0. */
        !           171:                        outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
        !           172: 
        !           173:                        irq = inw(ioaddr + WN0_IRQ) >> 12;
        !           174:                        if_port = inw(ioaddr + 6)>>14;
        !           175:                        for (i = 0; i < 3; i++)
        !           176:                                phys_addr[i] = htons(read_eeprom(ioaddr, i));
        !           177: 
        !           178:                        /* Restore the "Product ID" to the EEPROM read register. */
        !           179:                        read_eeprom(ioaddr, 3);
        !           180: 
        !           181:                        /* Was the EISA code an add-on hack?  Nahhhhh... */
        !           182:                        goto found;
        !           183:                }
        !           184:        }
        !           185: 
        !           186: #ifdef CONFIG_MCA
        !           187:        if (MCA_bus) {
        !           188:                mca_adaptor_select_mode(1);
        !           189:                for (i = 0; i < 8; i++)
        !           190:                        if ((mca_adaptor_id(i) | 1) == 0x627c) {
        !           191:                                ioaddr = mca_pos_base_addr(i);
        !           192:                                irq = inw(ioaddr + WN0_IRQ) >> 12;
        !           193:                                if_port = inw(ioaddr + 6)>>14;
        !           194:                                for (i = 0; i < 3; i++)
        !           195:                                        phys_addr[i] = htons(read_eeprom(ioaddr, i));
        !           196: 
        !           197:                                mca_adaptor_select_mode(0);
        !           198:                                goto found;
        !           199:                        }
        !           200:                mca_adaptor_select_mode(0);
        !           201: 
        !           202:        }
        !           203: #endif
        !           204: 
        !           205:        /* Reset the ISA PnP mechanism on 3c509b. */
        !           206:        outb(0x02, 0x279);           /* Select PnP config control register. */
        !           207:        outb(0x02, 0xA79);           /* Return to WaitForKey state. */
        !           208:        /* Select an open I/O location at 0x1*0 to do contention select. */
        !           209:        for ( ; id_port < 0x200; id_port += 0x10) {
        !           210:                if (check_region(id_port, 1))
        !           211:                        continue;
        !           212:                outb(0x00, id_port);
        !           213:                outb(0xff, id_port);
        !           214:                if (inb(id_port) & 0x01)
        !           215:                        break;
        !           216:        }
        !           217:        if (id_port >= 0x200) {             /* GCC optimizes this test out. */
        !           218:                /* Rare -- do we really need a warning? */
        !           219:                printk(" WARNING: No I/O port available for 3c509 activation.\n");
        !           220:                return -ENODEV;
        !           221:        }
        !           222:        /* Next check for all ISA bus boards by sending the ID sequence to the
        !           223:           ID_PORT.  We find cards past the first by setting the 'current_tag'
        !           224:           on cards as they are found.  Cards with their tag set will not
        !           225:           respond to subsequent ID sequences. */
        !           226: 
        !           227:        outb(0x00, id_port);
        !           228:        outb(0x00, id_port);
        !           229:        for(i = 0; i < 255; i++) {
        !           230:                outb(lrs_state, id_port);
        !           231:                lrs_state <<= 1;
        !           232:                lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
        !           233:        }
        !           234: 
        !           235:        /* For the first probe, clear all board's tag registers. */
        !           236:        if (current_tag == 0)
        !           237:                outb(0xd0, id_port);
        !           238:        else                            /* Otherwise kill off already-found boards. */
        !           239:                outb(0xd8, id_port);
        !           240: 
        !           241:        if (id_read_eeprom(7) != 0x6d50) {
        !           242:                return -ENODEV;
        !           243:        }
        !           244: 
        !           245:        /* Read in EEPROM data, which does contention-select.
        !           246:           Only the lowest address board will stay "on-line".
        !           247:           3Com got the byte order backwards. */
        !           248:        for (i = 0; i < 3; i++) {
        !           249:                phys_addr[i] = htons(id_read_eeprom(i));
        !           250:        }
        !           251: 
        !           252:        {
        !           253:                unsigned int iobase = id_read_eeprom(8);
        !           254:                if_port = iobase >> 14;
        !           255:                ioaddr = 0x200 + ((iobase & 0x1f) << 4);
        !           256:        }
        !           257:        irq = id_read_eeprom(9) >> 12;
        !           258: 
        !           259:        if (dev) {                                      /* Set passed-in IRQ or I/O Addr. */
        !           260:                if (dev->irq > 1  &&  dev->irq < 16)
        !           261:                        irq = dev->irq;
        !           262: 
        !           263:                if (dev->base_addr) {
        !           264:                        if (dev->mem_end == 0x3c509                     /* Magic key */
        !           265:                                && dev->base_addr >= 0x200  &&  dev->base_addr <= 0x3e0)
        !           266:                                ioaddr = dev->base_addr & 0x3f0;
        !           267:                        else if (dev->base_addr != ioaddr)
        !           268:                                return -ENODEV;
        !           269:                }
        !           270:        }
        !           271: 
        !           272:        /* Set the adaptor tag so that the next card can be found. */
        !           273:        outb(0xd0 + ++current_tag, id_port);
        !           274: 
        !           275:        /* Activate the adaptor at the EEPROM location. */
        !           276:        outb((ioaddr >> 4) | 0xe0, id_port);
        !           277: 
        !           278:        EL3WINDOW(0);
        !           279:        if (inw(ioaddr) != 0x6d50)
        !           280:                return -ENODEV;
        !           281: 
        !           282:        /* Free the interrupt so that some other card can use it. */
        !           283:        outw(0x0f00, ioaddr + WN0_IRQ);
        !           284:  found:
        !           285:        if (dev == NULL) {
        !           286:                dev = init_etherdev(dev, sizeof(struct el3_private));
        !           287:        }
        !           288:        memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
        !           289:        dev->base_addr = ioaddr;
        !           290:        dev->irq = irq;
        !           291:        dev->if_port = (dev->mem_start & 0x1f) ? dev->mem_start & 3 : if_port;
        !           292: 
        !           293:        request_region(dev->base_addr, EL3_IO_EXTENT, "3c509");
        !           294: 
        !           295:        {
        !           296:                const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
        !           297:                printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
        !           298:                           dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
        !           299:        }
        !           300: 
        !           301:        /* Read in the station address. */
        !           302:        for (i = 0; i < 6; i++)
        !           303:                printk(" %2.2x", dev->dev_addr[i]);
        !           304:        printk(", IRQ %d.\n", dev->irq);
        !           305: 
        !           306:        /* Make up a EL3-specific-data structure. */
        !           307:        if (dev->priv == NULL)
        !           308:                dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
        !           309:        if (dev->priv == NULL)
        !           310:                return -ENOMEM;
        !           311:        memset(dev->priv, 0, sizeof(struct el3_private));
        !           312: 
        !           313:        ((struct el3_private *)dev->priv)->next_dev = el3_root_dev;
        !           314:        el3_root_dev = dev;
        !           315: 
        !           316:        if (el3_debug > 0)
        !           317:                printk(version);
        !           318: 
        !           319:        /* The EL3-specific entries in the device structure. */
        !           320:        dev->open = &el3_open;
        !           321:        dev->hard_start_xmit = &el3_start_xmit;
        !           322:        dev->stop = &el3_close;
        !           323:        dev->get_stats = &el3_get_stats;
        !           324:        dev->set_multicast_list = &set_multicast_list;
        !           325: 
        !           326:        /* Fill in the generic fields of the device structure. */
        !           327:        ether_setup(dev);
        !           328:        return 0;
        !           329: }
        !           330: 
        !           331: /* Read a word from the EEPROM using the regular EEPROM access register.
        !           332:    Assume that we are in register window zero.
        !           333:  */
        !           334: static ushort read_eeprom(int ioaddr, int index)
        !           335: {
        !           336:        outw(EEPROM_READ + index, ioaddr + 10);
        !           337:        /* Pause for at least 162 us. for the read to take place. */
        !           338:        udelay (500);
        !           339:        return inw(ioaddr + 12);
        !           340: }
        !           341: 
        !           342: /* Read a word from the EEPROM when in the ISA ID probe state. */
        !           343: static ushort id_read_eeprom(int index)
        !           344: {
        !           345:        int bit, word = 0;
        !           346: 
        !           347:        /* Issue read command, and pause for at least 162 us. for it to complete.
        !           348:           Assume extra-fast 16Mhz bus. */
        !           349:        outb(EEPROM_READ + index, id_port);
        !           350: 
        !           351:        /* Pause for at least 162 us. for the read to take place. */
        !           352:        udelay (500);
        !           353:        
        !           354:        for (bit = 15; bit >= 0; bit--)
        !           355:                word = (word << 1) + (inb(id_port) & 0x01);
        !           356: 
        !           357:        if (el3_debug > 3)
        !           358:                printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
        !           359: 
        !           360:        return word;
        !           361: }
        !           362: 
        !           363: 
        !           364: 
        !           365: static int
        !           366: el3_open(struct device *dev)
        !           367: {
        !           368:        int ioaddr = dev->base_addr;
        !           369:        int i;
        !           370: 
        !           371:        outw(TxReset, ioaddr + EL3_CMD);
        !           372:        outw(RxReset, ioaddr + EL3_CMD);
        !           373:        outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
        !           374: 
        !           375:        if (request_irq(dev->irq, &el3_interrupt, 0, "3c509", dev)) {
        !           376:                return -EAGAIN;
        !           377:        }
        !           378: 
        !           379:        EL3WINDOW(0);
        !           380:        if (el3_debug > 3)
        !           381:                printk("%s: Opening, IRQ %d      status@%x %4.4x.\n", dev->name,
        !           382:                           dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
        !           383: 
        !           384:        /* Activate board: this is probably unnecessary. */
        !           385:        outw(0x0001, ioaddr + 4);
        !           386: 
        !           387:        /* Set the IRQ line. */
        !           388:        outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
        !           389: 
        !           390:        /* Set the station address in window 2 each time opened. */
        !           391:        EL3WINDOW(2);
        !           392: 
        !           393:        for (i = 0; i < 6; i++)
        !           394:                outb(dev->dev_addr[i], ioaddr + i);
        !           395: 
        !           396:        if (dev->if_port == 3)
        !           397:                /* Start the thinnet transceiver. We should really wait 50ms...*/
        !           398:                outw(StartCoax, ioaddr + EL3_CMD);
        !           399:        else if (dev->if_port == 0) {
        !           400:                /* 10baseT interface, enabled link beat and jabber check. */
        !           401:                EL3WINDOW(4);
        !           402:                outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
        !           403:        }
        !           404: 
        !           405:        /* Switch to the stats window, and clear all stats by reading. */
        !           406:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           407:        EL3WINDOW(6);
        !           408:        for (i = 0; i < 9; i++)
        !           409:                inb(ioaddr + i);
        !           410:        inw(ioaddr + 10);
        !           411:        inw(ioaddr + 12);
        !           412: 
        !           413:        /* Switch to register set 1 for normal use. */
        !           414:        EL3WINDOW(1);
        !           415: 
        !           416:        /* Accept b-case and phys addr only. */
        !           417:        outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
        !           418:        outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
        !           419: 
        !           420:        dev->interrupt = 0;
        !           421:        dev->tbusy = 0;
        !           422:        dev->start = 1;
        !           423: 
        !           424:        outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
        !           425:        outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
        !           426:        /* Allow status bits to be seen. */
        !           427:        outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
        !           428:        /* Ack all pending events, and set active indicator mask. */
        !           429:        outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
        !           430:                 ioaddr + EL3_CMD);
        !           431:        outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
        !           432:                 ioaddr + EL3_CMD);
        !           433: 
        !           434:        if (el3_debug > 3)
        !           435:                printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
        !           436:                           dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
        !           437: 
        !           438:        MOD_INC_USE_COUNT;
        !           439:        return 0;                                       /* Always succeed */
        !           440: }
        !           441: 
        !           442: static int
        !           443: el3_start_xmit(struct sk_buff *skb, struct device *dev)
        !           444: {
        !           445:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           446:        int ioaddr = dev->base_addr;
        !           447: 
        !           448:        /* Transmitter timeout, serious problems. */
        !           449:        if (dev->tbusy) {
        !           450:                int tickssofar = jiffies - dev->trans_start;
        !           451:                if (tickssofar < TX_TIMEOUT)
        !           452:                        return 1;
        !           453:                printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
        !           454:                           "Tx FIFO room %d.\n",
        !           455:                           dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
        !           456:                           inw(ioaddr + TX_FREE));
        !           457:                lp->stats.tx_errors++;
        !           458:                dev->trans_start = jiffies;
        !           459:                /* Issue TX_RESET and TX_START commands. */
        !           460:                outw(TxReset, ioaddr + EL3_CMD);
        !           461:                outw(TxEnable, ioaddr + EL3_CMD);
        !           462:                dev->tbusy = 0;
        !           463:        }
        !           464: 
        !           465:        if (el3_debug > 4) {
        !           466:                printk("%s: el3_start_xmit(length = %ld) called, status %4.4x.\n",
        !           467:                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
        !           468:        }
        !           469: #if 0
        !           470: #ifndef final_version
        !           471:        {       /* Error-checking code, delete someday. */
        !           472:                ushort status = inw(ioaddr + EL3_STATUS);
        !           473:                if (status & 0x0001             /* IRQ line active, missed one. */
        !           474:                        && inw(ioaddr + EL3_STATUS) & 1) {                      /* Make sure. */
        !           475:                        printk("%s: Missed interrupt, status then %04x now %04x"
        !           476:                                   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
        !           477:                                   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
        !           478:                                   inw(ioaddr + RX_STATUS));
        !           479:                        /* Fake interrupt trigger by masking, acknowledge interrupts. */
        !           480:                        outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
        !           481:                        outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
        !           482:                                 ioaddr + EL3_CMD);
        !           483:                        outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
        !           484:                }
        !           485:        }
        !           486: #endif
        !           487: #endif
        !           488:        /* Avoid timer-based retransmission conflicts. */
        !           489:        if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           490:                printk("%s: Transmitter access conflict.\n", dev->name);
        !           491:        else {
        !           492:                /* Put out the doubleword header... */
        !           493:                outw(skb->len, ioaddr + TX_FIFO);
        !           494:                outw(0x00, ioaddr + TX_FIFO);
        !           495:                /* ... and the packet rounded to a doubleword. */
        !           496: #ifdef  __powerpc__
        !           497:                outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
        !           498: #else
        !           499:                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
        !           500: #endif
        !           501: 
        !           502:                dev->trans_start = jiffies;
        !           503:                if (inw(ioaddr + TX_FREE) > 1536) {
        !           504:                        dev->tbusy = 0;
        !           505:                } else
        !           506:                        /* Interrupt us when the FIFO has room for max-sized packet. */
        !           507:                        outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
        !           508:        }
        !           509: 
        !           510:        dev_kfree_skb (skb, FREE_WRITE);
        !           511: 
        !           512:        /* Clear the Tx status stack. */
        !           513:        {
        !           514:                short tx_status;
        !           515:                int i = 4;
        !           516: 
        !           517:                while (--i > 0  &&      (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
        !           518:                        if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
        !           519:                        if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
        !           520:                        if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
        !           521:                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
        !           522:                }
        !           523:        }
        !           524:        return 0;
        !           525: }
        !           526: 
        !           527: /* The EL3 interrupt handler. */
        !           528: static void
        !           529: el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        !           530: {
        !           531:        struct device *dev = (struct device *)dev_id;
        !           532:        int ioaddr, status;
        !           533:        int i = max_interrupt_work;
        !           534: 
        !           535:        if (dev == NULL) {
        !           536:                printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
        !           537:                return;
        !           538:        }
        !           539: 
        !           540:        if (dev->interrupt)
        !           541:                printk("%s: Re-entering the interrupt handler.\n", dev->name);
        !           542:        dev->interrupt = 1;
        !           543: 
        !           544:        ioaddr = dev->base_addr;
        !           545:        status = inw(ioaddr + EL3_STATUS);
        !           546: 
        !           547:        if (el3_debug > 4)
        !           548:                printk("%s: interrupt, status %4.4x.\n", dev->name, status);
        !           549: 
        !           550:        while ((status = inw(ioaddr + EL3_STATUS)) &
        !           551:                   (IntLatch | RxComplete | StatsFull)) {
        !           552: 
        !           553:                if (status & RxComplete)
        !           554:                        el3_rx(dev);
        !           555: 
        !           556:                if (status & TxAvailable) {
        !           557:                        if (el3_debug > 5)
        !           558:                                printk("        TX room bit was handled.\n");
        !           559:                        /* There's room in the FIFO for a full-sized packet. */
        !           560:                        outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
        !           561:                        dev->tbusy = 0;
        !           562:                        mark_bh(NET_BH);
        !           563:                }
        !           564:                if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
        !           565:                        /* Handle all uncommon interrupts. */
        !           566:                        if (status & StatsFull)                         /* Empty statistics. */
        !           567:                                update_stats(ioaddr, dev);
        !           568:                        if (status & RxEarly) {                         /* Rx early is unused. */
        !           569:                                el3_rx(dev);
        !           570:                                outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
        !           571:                        }
        !           572:                        if (status & TxComplete) {                      /* Really Tx error. */
        !           573:                                struct el3_private *lp = (struct el3_private *)dev->priv;
        !           574:                                short tx_status;
        !           575:                                int i = 4;
        !           576: 
        !           577:                                while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
        !           578:                                        if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
        !           579:                                        if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
        !           580:                                        if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
        !           581:                                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
        !           582:                                }
        !           583:                        }
        !           584:                        if (status & AdapterFailure) {
        !           585:                                /* Adapter failure requires Rx reset and reinit. */
        !           586:                                outw(RxReset, ioaddr + EL3_CMD);
        !           587:                                /* Set the Rx filter to the current state. */
        !           588:                                outw(SetRxFilter | RxStation | RxBroadcast
        !           589:                                         | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
        !           590:                                         | (dev->flags & IFF_PROMISC ? RxProm : 0),
        !           591:                                         ioaddr + EL3_CMD);
        !           592:                                outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
        !           593:                                outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
        !           594:                        }
        !           595:                }
        !           596: 
        !           597:                if (--i < 0) {
        !           598:                        printk("%s: Infinite loop in interrupt, status %4.4x.\n",
        !           599:                                   dev->name, status);
        !           600:                        /* Clear all interrupts. */
        !           601:                        outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
        !           602:                        break;
        !           603:                }
        !           604:                /* Acknowledge the IRQ. */
        !           605:                outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
        !           606:        }
        !           607: 
        !           608:        if (el3_debug > 4) {
        !           609:                printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
        !           610:                           inw(ioaddr + EL3_STATUS));
        !           611:        }
        !           612: 
        !           613:        dev->interrupt = 0;
        !           614:        return;
        !           615: }
        !           616: 
        !           617: 
        !           618: static struct enet_statistics *
        !           619: el3_get_stats(struct device *dev)
        !           620: {
        !           621:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           622:        unsigned long flags;
        !           623: 
        !           624:        save_flags(flags);
        !           625:        cli();
        !           626:        update_stats(dev->base_addr, dev);
        !           627:        restore_flags(flags);
        !           628:        return &lp->stats;
        !           629: }
        !           630: 
        !           631: /*  Update statistics.  We change to register window 6, so this should be run
        !           632:        single-threaded if the device is active. This is expected to be a rare
        !           633:        operation, and it's simpler for the rest of the driver to assume that
        !           634:        window 1 is always valid rather than use a special window-state variable.
        !           635:        */
        !           636: static void update_stats(int ioaddr, struct device *dev)
        !           637: {
        !           638:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           639: 
        !           640:        if (el3_debug > 5)
        !           641:                printk("   Updating the statistics.\n");
        !           642:        /* Turn off statistics updates while reading. */
        !           643:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           644:        /* Switch to the stats window, and read everything. */
        !           645:        EL3WINDOW(6);
        !           646:        lp->stats.tx_carrier_errors     += inb(ioaddr + 0);
        !           647:        lp->stats.tx_heartbeat_errors   += inb(ioaddr + 1);
        !           648:        /* Multiple collisions. */              inb(ioaddr + 2);
        !           649:        lp->stats.collisions                    += inb(ioaddr + 3);
        !           650:        lp->stats.tx_window_errors              += inb(ioaddr + 4);
        !           651:        lp->stats.rx_fifo_errors                += inb(ioaddr + 5);
        !           652:        lp->stats.tx_packets                    += inb(ioaddr + 6);
        !           653:        /* Rx packets   */                              inb(ioaddr + 7);
        !           654:        /* Tx deferrals */                              inb(ioaddr + 8);
        !           655:        inw(ioaddr + 10);       /* Total Rx and Tx octets. */
        !           656:        inw(ioaddr + 12);
        !           657: 
        !           658:        /* Back to window 1, and turn statistics back on. */
        !           659:        EL3WINDOW(1);
        !           660:        outw(StatsEnable, ioaddr + EL3_CMD);
        !           661:        return;
        !           662: }
        !           663: 
        !           664: static int
        !           665: el3_rx(struct device *dev)
        !           666: {
        !           667:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           668:        int ioaddr = dev->base_addr;
        !           669:        short rx_status;
        !           670: 
        !           671:        if (el3_debug > 5)
        !           672:                printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
        !           673:                           inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
        !           674:        while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
        !           675:                if (rx_status & 0x4000) { /* Error, update stats. */
        !           676:                        short error = rx_status & 0x3800;
        !           677: 
        !           678:                        outw(RxDiscard, ioaddr + EL3_CMD);
        !           679:                        lp->stats.rx_errors++;
        !           680:                        switch (error) {
        !           681:                        case 0x0000:            lp->stats.rx_over_errors++; break;
        !           682:                        case 0x0800:            lp->stats.rx_length_errors++; break;
        !           683:                        case 0x1000:            lp->stats.rx_frame_errors++; break;
        !           684:                        case 0x1800:            lp->stats.rx_length_errors++; break;
        !           685:                        case 0x2000:            lp->stats.rx_frame_errors++; break;
        !           686:                        case 0x2800:            lp->stats.rx_crc_errors++; break;
        !           687:                        }
        !           688:                } else {
        !           689:                        short pkt_len = rx_status & 0x7ff;
        !           690:                        struct sk_buff *skb;
        !           691: 
        !           692:                        skb = dev_alloc_skb(pkt_len+5);
        !           693:                        if (el3_debug > 4)
        !           694:                                printk("Receiving packet size %d status %4.4x.\n",
        !           695:                                           pkt_len, rx_status);
        !           696:                        if (skb != NULL) {
        !           697:                                skb->dev = dev;
        !           698:                                skb_reserve(skb, 2);     /* Align IP on 16 byte */
        !           699: 
        !           700:                                /* 'skb->data' points to the start of sk_buff data area. */
        !           701: #ifdef  __powerpc__
        !           702:                                insl_unswapped(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
        !           703:                                                           (pkt_len + 3) >> 2);
        !           704: #else
        !           705:                                insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
        !           706:                                         (pkt_len + 3) >> 2);
        !           707: #endif
        !           708: 
        !           709:                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
        !           710:                                skb->protocol = eth_type_trans(skb,dev);
        !           711:                                netif_rx(skb);
        !           712:                                lp->stats.rx_packets++;
        !           713:                                continue;
        !           714:                        }
        !           715:                        outw(RxDiscard, ioaddr + EL3_CMD);
        !           716:                        lp->stats.rx_dropped++;
        !           717:                        if (el3_debug)
        !           718:                                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
        !           719:                                           dev->name, pkt_len);
        !           720:                }
        !           721:                inw(ioaddr + EL3_STATUS);                               /* Delay. */
        !           722:                while (inw(ioaddr + EL3_STATUS) & 0x1000)
        !           723:                        printk("        Waiting for 3c509 to discard packet, status %x.\n",
        !           724:                                   inw(ioaddr + EL3_STATUS) );
        !           725:        }
        !           726: 
        !           727:        return 0;
        !           728: }
        !           729: 
        !           730: /*
        !           731:  *     Set or clear the multicast filter for this adaptor.
        !           732:  */
        !           733: static void
        !           734: set_multicast_list(struct device *dev)
        !           735: {
        !           736:        int ioaddr = dev->base_addr;
        !           737:        if (el3_debug > 1) {
        !           738:                static int old = 0;
        !           739:                if (old != dev->mc_count) {
        !           740:                        old = dev->mc_count;
        !           741:                        printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count);
        !           742:                }
        !           743:        }
        !           744:        if (dev->flags&IFF_PROMISC) {
        !           745:                outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
        !           746:                         ioaddr + EL3_CMD);
        !           747:        }
        !           748:        else if (dev->mc_count || (dev->flags&IFF_ALLMULTI)) {
        !           749:                outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
        !           750:        }
        !           751:        else
        !           752:                 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
        !           753: }
        !           754: 
        !           755: static int
        !           756: el3_close(struct device *dev)
        !           757: {
        !           758:        int ioaddr = dev->base_addr;
        !           759: 
        !           760:        if (el3_debug > 2)
        !           761:                printk("%s: Shutting down ethercard.\n", dev->name);
        !           762: 
        !           763:        dev->tbusy = 1;
        !           764:        dev->start = 0;
        !           765: 
        !           766:        /* Turn off statistics ASAP.  We update lp->stats below. */
        !           767:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           768: 
        !           769:        /* Disable the receiver and transmitter. */
        !           770:        outw(RxDisable, ioaddr + EL3_CMD);
        !           771:        outw(TxDisable, ioaddr + EL3_CMD);
        !           772: 
        !           773:        if (dev->if_port == 3)
        !           774:                /* Turn off thinnet power.  Green! */
        !           775:                outw(StopCoax, ioaddr + EL3_CMD);
        !           776:        else if (dev->if_port == 0) {
        !           777:                /* Disable link beat and jabber, if_port may change ere next open(). */
        !           778:                EL3WINDOW(4);
        !           779:                outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
        !           780:        }
        !           781: 
        !           782:        free_irq(dev->irq, dev);
        !           783:        /* Switching back to window 0 disables the IRQ. */
        !           784:        EL3WINDOW(0);
        !           785:        /* But we explicitly zero the IRQ line select anyway. */
        !           786:        outw(0x0f00, ioaddr + WN0_IRQ);
        !           787: 
        !           788:        update_stats(ioaddr, dev);
        !           789:        MOD_DEC_USE_COUNT;
        !           790:        return 0;
        !           791: }
        !           792: 
        !           793: #ifdef MODULE
        !           794: /* Parameters that may be passed into the module. */
        !           795: static int debug = -1;
        !           796: static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
        !           797: static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
        !           798: 
        !           799: int
        !           800: init_module(void)
        !           801: {
        !           802:        int el3_cards = 0;
        !           803: 
        !           804:        if (debug >= 0)
        !           805:                el3_debug = debug;
        !           806: 
        !           807:        el3_root_dev = NULL;
        !           808:        while (el3_probe(0) == 0) {
        !           809:                if (irq[el3_cards] > 1)
        !           810:                        el3_root_dev->irq = irq[el3_cards];
        !           811:                if (xcvr[el3_cards] >= 0)
        !           812:                        el3_root_dev->if_port = xcvr[el3_cards];
        !           813:                el3_cards++;
        !           814:        }
        !           815: 
        !           816:        return el3_cards ? 0 : -ENODEV;
        !           817: }
        !           818: 
        !           819: void
        !           820: cleanup_module(void)
        !           821: {
        !           822:        struct device *next_dev;
        !           823: 
        !           824:        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        !           825:        while (el3_root_dev) {
        !           826:                next_dev = ((struct el3_private *)el3_root_dev->priv)->next_dev;
        !           827:                unregister_netdev(el3_root_dev);
        !           828:                release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
        !           829:                kfree(el3_root_dev);
        !           830:                el3_root_dev = next_dev;
        !           831:        }
        !           832: }
        !           833: #endif /* MODULE */
        !           834: 
        !           835: /*
        !           836:  * Local variables:
        !           837:  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c509.c"
        !           838:  *  version-control: t
        !           839:  *  kept-new-versions: 5
        !           840:  *  tab-width: 4
        !           841:  * End:
        !           842:  */

unix.superglobalmegacorp.com

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