Annotation of Gnu-Mach/i386/i386at/gpl/linux/net/3c509.c, revision 1.1

1.1     ! root        1: /* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
        !             2: /*
        !             3:        Written 1993,1994 by Donald Becker.
        !             4: 
        !             5:        Copyright 1994 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: static const  char *version = "3c509.c:1.03 10/8/94 [email protected]\n";
        !            28: 
        !            29: #include <linux/module.h>
        !            30: 
        !            31: #include <linux/config.h>
        !            32: #include <linux/kernel.h>
        !            33: #include <linux/sched.h>
        !            34: #include <linux/string.h>
        !            35: #include <linux/interrupt.h>
        !            36: #include <linux/ptrace.h>
        !            37: #include <linux/errno.h>
        !            38: #include <linux/in.h>
        !            39: #include <linux/malloc.h>
        !            40: #include <linux/ioport.h>
        !            41: #include <linux/netdevice.h>
        !            42: #include <linux/etherdevice.h>
        !            43: #include <linux/skbuff.h>
        !            44: #include <linux/config.h>      /* for CONFIG_MCA */
        !            45: 
        !            46: #include <asm/bitops.h>
        !            47: #include <asm/io.h>
        !            48: 
        !            49: 
        !            50: #ifdef EL3_DEBUG
        !            51: int el3_debug = EL3_DEBUG;
        !            52: #else
        !            53: int el3_debug = 2;
        !            54: #endif
        !            55: 
        !            56: /* To minimize the size of the driver source I only define operating
        !            57:    constants if they are used several times.  You'll need the manual
        !            58:    if you want to understand driver details. */
        !            59: /* Offsets from base I/O address. */
        !            60: #define EL3_DATA 0x00
        !            61: #define EL3_CMD 0x0e
        !            62: #define EL3_STATUS 0x0e
        !            63: #define ID_PORT 0x100
        !            64: #define         EEPROM_READ 0x80
        !            65: 
        !            66: #define EL3_IO_EXTENT  16
        !            67: 
        !            68: #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
        !            69: 
        !            70: 
        !            71: /* The top five bits written to EL3_CMD are a command, the lower
        !            72:    11 bits are the parameter, if applicable. */
        !            73: enum c509cmd {
        !            74:        TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
        !            75:        RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
        !            76:        TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
        !            77:        FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrMask = 14<<11,
        !            78:        SetReadZero = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
        !            79:        SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
        !            80:        StatsDisable = 22<<11, StopCoax = 23<<11,};
        !            81: 
        !            82: /* The SetRxFilter command accepts the following classes: */
        !            83: enum RxFilter {
        !            84:        RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
        !            85: 
        !            86: /* Register window 1 offsets, the window used in normal operation. */
        !            87: #define TX_FIFO                0x00
        !            88: #define RX_FIFO                0x00
        !            89: #define RX_STATUS      0x08
        !            90: #define TX_STATUS      0x0B
        !            91: #define TX_FREE                0x0C            /* Remaining free bytes in Tx buffer. */
        !            92: 
        !            93: #define WN0_IRQ                0x08            /* Window 0: Set IRQ line in bits 12-15. */
        !            94: #define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
        !            95: #define  MEDIA_TP      0x00C0          /* Enable link beat and jabber for 10baseT. */
        !            96: 
        !            97: struct el3_private {
        !            98:        struct enet_statistics stats;
        !            99: };
        !           100: 
        !           101: static ushort id_read_eeprom(int index);
        !           102: static ushort read_eeprom(short ioaddr, int index);
        !           103: static int el3_open(struct device *dev);
        !           104: static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
        !           105: static void el3_interrupt(int irq, struct pt_regs *regs);
        !           106: static void update_stats(int addr, struct device *dev);
        !           107: static struct enet_statistics *el3_get_stats(struct device *dev);
        !           108: static int el3_rx(struct device *dev);
        !           109: static int el3_close(struct device *dev);
        !           110: static void set_multicast_list(struct device *dev);
        !           111: 
        !           112: 
        !           113: 
        !           114: int el3_probe(struct device *dev)
        !           115: {
        !           116:        short lrs_state = 0xff, i;
        !           117:        ushort ioaddr, irq, if_port;
        !           118:        short *phys_addr = (short *)dev->dev_addr;
        !           119:        static int current_tag = 0;
        !           120: 
        !           121:        /* First check all slots of the EISA bus.  The next slot address to
        !           122:           probe is kept in 'eisa_addr' to support multiple probe() calls. */
        !           123:        if (EISA_bus) {
        !           124:                static int eisa_addr = 0x1000;
        !           125:                while (eisa_addr < 0x9000) {
        !           126:                        ioaddr = eisa_addr;
        !           127:                        eisa_addr += 0x1000;
        !           128: 
        !           129:                        /* Check the standard EISA ID register for an encoded '3Com'. */
        !           130:                        if (inw(ioaddr + 0xC80) != 0x6d50)
        !           131:                                continue;
        !           132: 
        !           133:                        /* Change the register set to the configuration window 0. */
        !           134:                        outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
        !           135: 
        !           136:                        irq = inw(ioaddr + WN0_IRQ) >> 12;
        !           137:                        if_port = inw(ioaddr + 6)>>14;
        !           138:                        for (i = 0; i < 3; i++)
        !           139:                                phys_addr[i] = htons(read_eeprom(ioaddr, i));
        !           140: 
        !           141:                        /* Restore the "Product ID" to the EEPROM read register. */
        !           142:                        read_eeprom(ioaddr, 3);
        !           143: 
        !           144:                        /* Was the EISA code an add-on hack?  Nahhhhh... */
        !           145:                        goto found;
        !           146:                }
        !           147:        }
        !           148: 
        !           149: #ifdef CONFIG_MCA
        !           150:        if (MCA_bus) {
        !           151:                mca_adaptor_select_mode(1);
        !           152:                for (i = 0; i < 8; i++)
        !           153:                        if ((mca_adaptor_id(i) | 1) == 0x627c) {
        !           154:                                ioaddr = mca_pos_base_addr(i);
        !           155:                                irq = inw(ioaddr + WN0_IRQ) >> 12;
        !           156:                                if_port = inw(ioaddr + 6)>>14;
        !           157:                                for (i = 0; i < 3; i++)
        !           158:                                        phys_addr[i] = htons(read_eeprom(ioaddr, i));
        !           159: 
        !           160:                                mca_adaptor_select_mode(0);
        !           161:                                goto found;
        !           162:                        }
        !           163:                mca_adaptor_select_mode(0);
        !           164: 
        !           165:        }
        !           166: #endif
        !           167: 
        !           168:        /* Next check for all ISA bus boards by sending the ID sequence to the
        !           169:           ID_PORT.  We find cards past the first by setting the 'current_tag'
        !           170:           on cards as they are found.  Cards with their tag set will not
        !           171:           respond to subsequent ID sequences. */
        !           172: 
        !           173:        if (check_region(ID_PORT,1)) {
        !           174:          static int once = 1;
        !           175:          if (once) printk("3c509: Somebody has reserved 0x%x, can't do ID_PORT lookup, nor card auto-probing\n",ID_PORT);
        !           176:          once = 0;
        !           177:          return -ENODEV;
        !           178:        }
        !           179: 
        !           180:        outb(0x00, ID_PORT);
        !           181:        outb(0x00, ID_PORT);
        !           182:        for(i = 0; i < 255; i++) {
        !           183:                outb(lrs_state, ID_PORT);
        !           184:                lrs_state <<= 1;
        !           185:                lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
        !           186:        }
        !           187: 
        !           188:        /* For the first probe, clear all board's tag registers. */
        !           189:        if (current_tag == 0)
        !           190:                outb(0xd0, ID_PORT);
        !           191:        else                            /* Otherwise kill off already-found boards. */
        !           192:                outb(0xd8, ID_PORT);
        !           193: 
        !           194:        if (id_read_eeprom(7) != 0x6d50) {
        !           195:                return -ENODEV;
        !           196:        }
        !           197: 
        !           198:        /* Read in EEPROM data, which does contention-select.
        !           199:           Only the lowest address board will stay "on-line".
        !           200:           3Com got the byte order backwards. */
        !           201:        for (i = 0; i < 3; i++) {
        !           202:                phys_addr[i] = htons(id_read_eeprom(i));
        !           203:        }
        !           204: 
        !           205:        {
        !           206:                unsigned short iobase = id_read_eeprom(8);
        !           207:                if_port = iobase >> 14;
        !           208:                ioaddr = 0x200 + ((iobase & 0x1f) << 4);
        !           209:        }
        !           210:        irq = id_read_eeprom(9) >> 12;
        !           211: 
        !           212:        if (dev->base_addr != 0
        !           213:                &&      dev->base_addr != (unsigned short)ioaddr) {
        !           214:                return -ENODEV;
        !           215:        }
        !           216: 
        !           217:        /* Set the adaptor tag so that the next card can be found. */
        !           218:        outb(0xd0 + ++current_tag, ID_PORT);
        !           219: 
        !           220:        /* Activate the adaptor at the EEPROM location. */
        !           221:        outb(0xff, ID_PORT);
        !           222: 
        !           223:        EL3WINDOW(0);
        !           224:        if (inw(ioaddr) != 0x6d50)
        !           225:                return -ENODEV;
        !           226: 
        !           227:        /* Free the interrupt so that some other card can use it. */
        !           228:        outw(0x0f00, ioaddr + WN0_IRQ);
        !           229:  found:
        !           230:        dev->base_addr = ioaddr;
        !           231:        dev->irq = irq;
        !           232:        dev->if_port = if_port;
        !           233:        request_region(dev->base_addr, EL3_IO_EXTENT, "3c509");
        !           234: 
        !           235:        {
        !           236:                const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
        !           237:                printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
        !           238:                           dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
        !           239:        }
        !           240: 
        !           241:        /* Read in the station address. */
        !           242:        for (i = 0; i < 6; i++)
        !           243:                printk(" %2.2x", dev->dev_addr[i]);
        !           244:        printk(", IRQ %d.\n", dev->irq);
        !           245: 
        !           246:        /* Make up a EL3-specific-data structure. */
        !           247:        dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
        !           248:        if (dev->priv == NULL)
        !           249:                return -ENOMEM;
        !           250:        memset(dev->priv, 0, sizeof(struct el3_private));
        !           251: 
        !           252:        if (el3_debug > 0)
        !           253:                printk(version);
        !           254: 
        !           255:        /* The EL3-specific entries in the device structure. */
        !           256:        dev->open = &el3_open;
        !           257:        dev->hard_start_xmit = &el3_start_xmit;
        !           258:        dev->stop = &el3_close;
        !           259:        dev->get_stats = &el3_get_stats;
        !           260:        dev->set_multicast_list = &set_multicast_list;
        !           261: 
        !           262:        /* Fill in the generic fields of the device structure. */
        !           263:        ether_setup(dev);
        !           264:        return 0;
        !           265: }
        !           266: 
        !           267: /* Read a word from the EEPROM using the regular EEPROM access register.
        !           268:    Assume that we are in register window zero.
        !           269:  */
        !           270: static ushort read_eeprom(short ioaddr, int index)
        !           271: {
        !           272:        int timer;
        !           273: 
        !           274:        outw(EEPROM_READ + index, ioaddr + 10);
        !           275:        /* Pause for at least 162 us. for the read to take place. */
        !           276:        for (timer = 0; timer < 162*4 + 400; timer++)
        !           277:                SLOW_DOWN_IO;
        !           278:        return inw(ioaddr + 12);
        !           279: }
        !           280: 
        !           281: /* Read a word from the EEPROM when in the ISA ID probe state. */
        !           282: static ushort id_read_eeprom(int index)
        !           283: {
        !           284:        int timer, bit, word = 0;
        !           285: 
        !           286:        /* Issue read command, and pause for at least 162 us. for it to complete.
        !           287:           Assume extra-fast 16Mhz bus. */
        !           288:        outb(EEPROM_READ + index, ID_PORT);
        !           289: 
        !           290:        /* This should really be done by looking at one of the timer channels. */
        !           291:        for (timer = 0; timer < 162*4 + 400; timer++)
        !           292:                SLOW_DOWN_IO;
        !           293: 
        !           294:        for (bit = 15; bit >= 0; bit--)
        !           295:                word = (word << 1) + (inb(ID_PORT) & 0x01);
        !           296: 
        !           297:        if (el3_debug > 3)
        !           298:                printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
        !           299: 
        !           300:        return word;
        !           301: }
        !           302: 
        !           303: 
        !           304: 
        !           305: static int
        !           306: el3_open(struct device *dev)
        !           307: {
        !           308:        int ioaddr = dev->base_addr;
        !           309:        int i;
        !           310: 
        !           311:        outw(TxReset, ioaddr + EL3_CMD);
        !           312:        outw(RxReset, ioaddr + EL3_CMD);
        !           313:        outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
        !           314: 
        !           315:        if (request_irq(dev->irq, &el3_interrupt, 0, "3c509")) {
        !           316:                return -EAGAIN;
        !           317:        }
        !           318: 
        !           319:        EL3WINDOW(0);
        !           320:        if (el3_debug > 3)
        !           321:                printk("%s: Opening, IRQ %d      status@%x %4.4x.\n", dev->name,
        !           322:                           dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
        !           323: 
        !           324:        /* Activate board: this is probably unnecessary. */
        !           325:        outw(0x0001, ioaddr + 4);
        !           326: 
        !           327:        irq2dev_map[dev->irq] = dev;
        !           328: 
        !           329:        /* Set the IRQ line. */
        !           330:        outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
        !           331: 
        !           332:        /* Set the station address in window 2 each time opened. */
        !           333:        EL3WINDOW(2);
        !           334: 
        !           335:        for (i = 0; i < 6; i++)
        !           336:                outb(dev->dev_addr[i], ioaddr + i);
        !           337: 
        !           338:        if (dev->if_port == 3)
        !           339:                /* Start the thinnet transceiver. We should really wait 50ms...*/
        !           340:                outw(StartCoax, ioaddr + EL3_CMD);
        !           341:        else if (dev->if_port == 0) {
        !           342:                /* 10baseT interface, enabled link beat and jabber check. */
        !           343:                EL3WINDOW(4);
        !           344:                outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
        !           345:        }
        !           346: 
        !           347:        /* Switch to the stats window, and clear all stats by reading. */
        !           348:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           349:        EL3WINDOW(6);
        !           350:        for (i = 0; i < 9; i++)
        !           351:                inb(ioaddr + i);
        !           352:        inb(ioaddr + 10);
        !           353:        inb(ioaddr + 12);
        !           354: 
        !           355:        /* Switch to register set 1 for normal use. */
        !           356:        EL3WINDOW(1);
        !           357: 
        !           358:        /* Accept b-case and phys addr only. */
        !           359:        outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
        !           360:        outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
        !           361: 
        !           362:        dev->interrupt = 0;
        !           363:        dev->tbusy = 0;
        !           364:        dev->start = 1;
        !           365: 
        !           366:        outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
        !           367:        outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
        !           368:        /* Allow status bits to be seen. */
        !           369:        outw(SetReadZero | 0xff, ioaddr + EL3_CMD);
        !           370:        outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */
        !           371:        outw(SetIntrMask | 0x98, ioaddr + EL3_CMD); /* Set interrupt mask. */
        !           372: 
        !           373:        if (el3_debug > 3)
        !           374:                printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
        !           375:                           dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
        !           376: 
        !           377:        MOD_INC_USE_COUNT;
        !           378:        return 0;                                       /* Always succeed */
        !           379: }
        !           380: 
        !           381: static int
        !           382: el3_start_xmit(struct sk_buff *skb, struct device *dev)
        !           383: {
        !           384:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           385:        int ioaddr = dev->base_addr;
        !           386: 
        !           387:        /* Transmitter timeout, serious problems. */
        !           388:        if (dev->tbusy) {
        !           389:                int tickssofar = jiffies - dev->trans_start;
        !           390:                if (tickssofar < 10)
        !           391:                        return 1;
        !           392:                printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
        !           393:                           dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
        !           394:                dev->trans_start = jiffies;
        !           395:                /* Issue TX_RESET and TX_START commands. */
        !           396:                outw(TxReset, ioaddr + EL3_CMD);
        !           397:                outw(TxEnable, ioaddr + EL3_CMD);
        !           398:                dev->tbusy = 0;
        !           399:        }
        !           400: 
        !           401:        if (skb == NULL) {
        !           402:                dev_tint(dev);
        !           403:                return 0;
        !           404:        }
        !           405: 
        !           406:        if (skb->len <= 0)
        !           407:                return 0;
        !           408: 
        !           409:        if (el3_debug > 4) {
        !           410:                printk("%s: el3_start_xmit(length = %ld) called, status %4.4x.\n",
        !           411:                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
        !           412:        }
        !           413: #ifndef final_version
        !           414:        {       /* Error-checking code, delete for 1.30. */
        !           415:                ushort status = inw(ioaddr + EL3_STATUS);
        !           416:                if (status & 0x0001             /* IRQ line active, missed one. */
        !           417:                        && inw(ioaddr + EL3_STATUS) & 1) {                      /* Make sure. */
        !           418:                        printk("%s: Missed interrupt, status then %04x now %04x"
        !           419:                                   "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
        !           420:                                   inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
        !           421:                                   inw(ioaddr + RX_STATUS));
        !           422:                        /* Fake interrupt trigger by masking, acknowledge interrupts. */
        !           423:                        outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
        !           424:                        outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */
        !           425:                        outw(SetReadZero | 0xff, ioaddr + EL3_CMD);
        !           426:                }
        !           427:        }
        !           428: #endif
        !           429: 
        !           430:        /* Avoid timer-based retransmission conflicts. */
        !           431:        if (set_bit(0, (void*)&dev->tbusy) != 0)
        !           432:                printk("%s: Transmitter access conflict.\n", dev->name);
        !           433:        else {
        !           434:                /* Put out the doubleword header... */
        !           435:                outw(skb->len, ioaddr + TX_FIFO);
        !           436:                outw(0x00, ioaddr + TX_FIFO);
        !           437:                /* ... and the packet rounded to a doubleword. */
        !           438:                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
        !           439: 
        !           440:                dev->trans_start = jiffies;
        !           441:                if (inw(ioaddr + TX_FREE) > 1536) {
        !           442:                        dev->tbusy = 0;
        !           443:                } else
        !           444:                        /* Interrupt us when the FIFO has room for max-sized packet. */
        !           445:                        outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
        !           446:        }
        !           447: 
        !           448:        dev_kfree_skb (skb, FREE_WRITE);
        !           449: 
        !           450:        /* Clear the Tx status stack. */
        !           451:        {
        !           452:                short tx_status;
        !           453:                int i = 4;
        !           454: 
        !           455:                while (--i > 0  &&      (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
        !           456:                        if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
        !           457:                        if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
        !           458:                        if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
        !           459:                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
        !           460:                }
        !           461:        }
        !           462:        return 0;
        !           463: }
        !           464: 
        !           465: /* The EL3 interrupt handler. */
        !           466: static void
        !           467: el3_interrupt(int irq, struct pt_regs *regs)
        !           468: {
        !           469:        struct device *dev = (struct device *)(irq2dev_map[irq]);
        !           470:        int ioaddr, status;
        !           471:        int i = 0;
        !           472: 
        !           473:        if (dev == NULL) {
        !           474:                printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
        !           475:                return;
        !           476:        }
        !           477: 
        !           478:        if (dev->interrupt)
        !           479:                printk("%s: Re-entering the interrupt handler.\n", dev->name);
        !           480:        dev->interrupt = 1;
        !           481: 
        !           482:        ioaddr = dev->base_addr;
        !           483:        status = inw(ioaddr + EL3_STATUS);
        !           484: 
        !           485:        if (el3_debug > 4)
        !           486:                printk("%s: interrupt, status %4.4x.\n", dev->name, status);
        !           487: 
        !           488:        while ((status = inw(ioaddr + EL3_STATUS)) & 0x91) {
        !           489: 
        !           490:                if (status & 0x10)
        !           491:                        el3_rx(dev);
        !           492: 
        !           493:                if (status & 0x08) {
        !           494:                        if (el3_debug > 5)
        !           495:                                printk("        TX room bit was handled.\n");
        !           496:                        /* There's room in the FIFO for a full-sized packet. */
        !           497:                        outw(AckIntr | 0x08, ioaddr + EL3_CMD);
        !           498:                        dev->tbusy = 0;
        !           499:                        mark_bh(NET_BH);
        !           500:                }
        !           501:                if (status & 0x80)                              /* Statistics full. */
        !           502:                        update_stats(ioaddr, dev);
        !           503: 
        !           504:                if (++i > 10) {
        !           505:                        printk("%s: Infinite loop in interrupt, status %4.4x.\n",
        !           506:                                   dev->name, status);
        !           507:                        /* Clear all interrupts. */
        !           508:                        outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
        !           509:                        break;
        !           510:                }
        !           511:                /* Acknowledge the IRQ. */
        !           512:                outw(AckIntr | 0x41, ioaddr + EL3_CMD); /* Ack IRQ */
        !           513: 
        !           514:        }
        !           515: 
        !           516:        if (el3_debug > 4) {
        !           517:                printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
        !           518:                           inw(ioaddr + EL3_STATUS));
        !           519:        }
        !           520: 
        !           521:        dev->interrupt = 0;
        !           522:        return;
        !           523: }
        !           524: 
        !           525: 
        !           526: static struct enet_statistics *
        !           527: el3_get_stats(struct device *dev)
        !           528: {
        !           529:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           530:        unsigned long flags;
        !           531: 
        !           532:        save_flags(flags);
        !           533:        cli();
        !           534:        update_stats(dev->base_addr, dev);
        !           535:        restore_flags(flags);
        !           536:        return &lp->stats;
        !           537: }
        !           538: 
        !           539: /*  Update statistics.  We change to register window 6, so this should be run
        !           540:        single-threaded if the device is active. This is expected to be a rare
        !           541:        operation, and it's simpler for the rest of the driver to assume that
        !           542:        window 1 is always valid rather than use a special window-state variable.
        !           543:        */
        !           544: static void update_stats(int ioaddr, struct device *dev)
        !           545: {
        !           546:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           547: 
        !           548:        if (el3_debug > 5)
        !           549:                printk("   Updating the statistics.\n");
        !           550:        /* Turn off statistics updates while reading. */
        !           551:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           552:        /* Switch to the stats window, and read everything. */
        !           553:        EL3WINDOW(6);
        !           554:        lp->stats.tx_carrier_errors     += inb(ioaddr + 0);
        !           555:        lp->stats.tx_heartbeat_errors   += inb(ioaddr + 1);
        !           556:        /* Multiple collisions. */              inb(ioaddr + 2);
        !           557:        lp->stats.collisions                    += inb(ioaddr + 3);
        !           558:        lp->stats.tx_window_errors              += inb(ioaddr + 4);
        !           559:        lp->stats.rx_fifo_errors                += inb(ioaddr + 5);
        !           560:        lp->stats.tx_packets                    += inb(ioaddr + 6);
        !           561:        /* Rx packets   */                              inb(ioaddr + 7);
        !           562:        /* Tx deferrals */                              inb(ioaddr + 8);
        !           563:        inw(ioaddr + 10);       /* Total Rx and Tx octets. */
        !           564:        inw(ioaddr + 12);
        !           565: 
        !           566:        /* Back to window 1, and turn statistics back on. */
        !           567:        EL3WINDOW(1);
        !           568:        outw(StatsEnable, ioaddr + EL3_CMD);
        !           569:        return;
        !           570: }
        !           571: 
        !           572: static int
        !           573: el3_rx(struct device *dev)
        !           574: {
        !           575:        struct el3_private *lp = (struct el3_private *)dev->priv;
        !           576:        int ioaddr = dev->base_addr;
        !           577:        short rx_status;
        !           578: 
        !           579:        if (el3_debug > 5)
        !           580:                printk("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
        !           581:                           inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
        !           582:        while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
        !           583:                if (rx_status & 0x4000) { /* Error, update stats. */
        !           584:                        short error = rx_status & 0x3800;
        !           585:                        lp->stats.rx_errors++;
        !           586:                        switch (error) {
        !           587:                        case 0x0000:            lp->stats.rx_over_errors++; break;
        !           588:                        case 0x0800:            lp->stats.rx_length_errors++; break;
        !           589:                        case 0x1000:            lp->stats.rx_frame_errors++; break;
        !           590:                        case 0x1800:            lp->stats.rx_length_errors++; break;
        !           591:                        case 0x2000:            lp->stats.rx_frame_errors++; break;
        !           592:                        case 0x2800:            lp->stats.rx_crc_errors++; break;
        !           593:                        }
        !           594:                } else {
        !           595:                        short pkt_len = rx_status & 0x7ff;
        !           596:                        struct sk_buff *skb;
        !           597: 
        !           598:                        skb = dev_alloc_skb(pkt_len+5);
        !           599:                        if (el3_debug > 4)
        !           600:                                printk("Receiving packet size %d status %4.4x.\n",
        !           601:                                           pkt_len, rx_status);
        !           602:                        if (skb != NULL) {
        !           603:                                skb->dev = dev;
        !           604:                                skb_reserve(skb,2);     /* Align IP on 16 byte boundaries */
        !           605: 
        !           606:                                /* 'skb->data' points to the start of sk_buff data area. */
        !           607:                                insl(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
        !           608:                                                        (pkt_len + 3) >> 2);
        !           609: 
        !           610:                                skb->protocol=eth_type_trans(skb,dev);
        !           611:                                netif_rx(skb);
        !           612:                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
        !           613:                                lp->stats.rx_packets++;
        !           614:                                continue;
        !           615:                        } else if (el3_debug)
        !           616:                                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
        !           617:                                           dev->name, pkt_len);
        !           618:                }
        !           619:                lp->stats.rx_dropped++;
        !           620:                outw(RxDiscard, ioaddr + EL3_CMD);
        !           621:                while (inw(ioaddr + EL3_STATUS) & 0x1000)
        !           622:                        printk("        Waiting for 3c509 to discard packet, status %x.\n",
        !           623:                                   inw(ioaddr + EL3_STATUS) );
        !           624:        }
        !           625: 
        !           626:        return 0;
        !           627: }
        !           628: 
        !           629: /* 
        !           630:  *     Set or clear the multicast filter for this adaptor.
        !           631:  */
        !           632:  
        !           633: static void set_multicast_list(struct device *dev)
        !           634: {
        !           635:        short ioaddr = dev->base_addr;
        !           636:        if (el3_debug > 1) {
        !           637:                static int old = 0;
        !           638:                if (old != dev->mc_count) {
        !           639:                        old = dev->mc_count;
        !           640:                        printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count);
        !           641:                }
        !           642:        }
        !           643:        if (dev->flags&IFF_PROMISC) 
        !           644:        {
        !           645:                outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
        !           646:                         ioaddr + EL3_CMD);
        !           647:        }
        !           648:        else if (dev->mc_count || (dev->flags&IFF_ALLMULTI)) 
        !           649:        {
        !           650:                outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
        !           651:        } 
        !           652:        else
        !           653:                outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
        !           654: }
        !           655: 
        !           656: static int
        !           657: el3_close(struct device *dev)
        !           658: {
        !           659:        int ioaddr = dev->base_addr;
        !           660: 
        !           661:        if (el3_debug > 2)
        !           662:                printk("%s: Shutting down ethercard.\n", dev->name);
        !           663: 
        !           664:        dev->tbusy = 1;
        !           665:        dev->start = 0;
        !           666: 
        !           667:        /* Turn off statistics ASAP.  We update lp->stats below. */
        !           668:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           669: 
        !           670:        /* Disable the receiver and transmitter. */
        !           671:        outw(RxDisable, ioaddr + EL3_CMD);
        !           672:        outw(TxDisable, ioaddr + EL3_CMD);
        !           673: 
        !           674:        if (dev->if_port == 3)
        !           675:                /* Turn off thinnet power.  Green! */
        !           676:                outw(StopCoax, ioaddr + EL3_CMD);
        !           677:        else if (dev->if_port == 0) {
        !           678:                /* Disable link beat and jabber, if_port may change ere next open(). */
        !           679:                EL3WINDOW(4);
        !           680:                outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
        !           681:        }
        !           682: 
        !           683:        free_irq(dev->irq);
        !           684:        /* Switching back to window 0 disables the IRQ. */
        !           685:        EL3WINDOW(0);
        !           686:        /* But we explicitly zero the IRQ line select anyway. */
        !           687:        outw(0x0f00, ioaddr + WN0_IRQ);
        !           688: 
        !           689: 
        !           690:        irq2dev_map[dev->irq] = 0;
        !           691: 
        !           692:        update_stats(ioaddr, dev);
        !           693:        MOD_DEC_USE_COUNT;
        !           694:        return 0;
        !           695: }
        !           696: 
        !           697: #ifdef MODULE
        !           698: static char devicename[9] = { 0, };
        !           699: static struct device dev_3c509 = {
        !           700:        devicename, /* device name is inserted by linux/drivers/net/net_init.c */
        !           701:        0, 0, 0, 0,
        !           702:        0, 0,
        !           703:        0, 0, 0, NULL, el3_probe };
        !           704: 
        !           705: static int io = 0;
        !           706: static int irq = 0;
        !           707: 
        !           708: int
        !           709: init_module(void)
        !           710: {
        !           711:        dev_3c509.base_addr = io;
        !           712:        dev_3c509.irq       = irq;
        !           713:        if (!EISA_bus) {
        !           714:                printk("3c509: WARNING! Module load-time probing works reliably only for EISA-bus!\n");
        !           715:        }
        !           716:        if (register_netdev(&dev_3c509) != 0)
        !           717:                return -EIO;
        !           718:        return 0;
        !           719: }
        !           720: 
        !           721: void
        !           722: cleanup_module(void)
        !           723: {
        !           724:        unregister_netdev(&dev_3c509);
        !           725:        kfree_s(dev_3c509.priv,sizeof(struct el3_private));
        !           726:        dev_3c509.priv=NULL;
        !           727:        /* If we don't do this, we can't re-insmod it later. */
        !           728:        release_region(dev_3c509.base_addr, EL3_IO_EXTENT);
        !           729: }
        !           730: #endif /* MODULE */
        !           731: 
        !           732: /*
        !           733:  * Local variables:
        !           734:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
        !           735:  *  version-control: t
        !           736:  *  kept-new-versions: 5
        !           737:  *  tab-width: 4
        !           738:  * End:
        !           739:  */

unix.superglobalmegacorp.com

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