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

1.1     ! root        1: /* $Id: eexpress.c,v 1.1 1999/04/26 05:52:09 tb Exp $
        !             2:  *
        !             3:  * Intel EtherExpress device driver for Linux
        !             4:  *
        !             5:  * Original version written 1993 by Donald Becker
        !             6:  * Modularized by Pauline Middelink <[email protected]>
        !             7:  * Changed to support io= irq= by Alan Cox <[email protected]>
        !             8:  * Reworked 1995 by John Sullivan <[email protected]>
        !             9:  * More fixes by Philip Blundell <[email protected]>
        !            10:  * Added the Compaq LTE  Alan Cox <[email protected]>
        !            11:  *
        !            12:  * Note - this driver is experimental still - it has problems on faster
        !            13:  * machines. Someone needs to sit down and go through it line by line with
        !            14:  * a databook...
        !            15:  */
        !            16: 
        !            17: /*
        !            18:  * The original EtherExpress driver was just about usable, but
        !            19:  * suffered from a long startup delay, a hard limit of 16k memory
        !            20:  * usage on the card (EtherExpress 16s have either 32k or 64k),
        !            21:  * and random locks under load. The last was particularly annoying
        !            22:  * and made running eXceed/W preferable to Linux/XFree. After hacking
        !            23:  * through the driver for a couple of days, I had fixed most of the
        !            24:  * card handling errors, at the expense of turning the code into
        !            25:  * a complete jungle, but still hadn't tracked down the lock-ups.
        !            26:  * I had hoped these would be an IP bug, but failed to reproduce them
        !            27:  * under other drivers, so decided to start from scratch and rewrite
        !            28:  * the driver cleanly. And here it is.
        !            29:  *
        !            30:  * It's still not quite there, but self-corrects a lot more problems.
        !            31:  * the 'CU wedged, resetting...' message shouldn't happen at all, but
        !            32:  * at least we recover. It still locks occasionally, any ideas welcome.
        !            33:  *
        !            34:  * The original startup delay experienced by some people was due to the
        !            35:  * first ARP request for the address of the default router getting lost.
        !            36:  * (mostly the reply we were getting back was arriving before our
        !            37:  * hardware address was set up, or before the configuration sequence
        !            38:  * had told the card NOT to strip of the frame header). If you a long
        !            39:  * startup delay, you may have lost this ARP request/reply, although
        !            40:  * the original cause has been fixed. However, it is more likely that
        !            41:  * you've just locked under this version.
        !            42:  *
        !            43:  * The main changes are in the 586 initialization procedure (which was
        !            44:  * just broken before - the EExp is a strange beasty and needs careful
        !            45:  * handling) the receive buffer handling (we now use a non-terminating
        !            46:  * circular list of buffers, which stops the card giving us out-of-
        !            47:  * resources errors), and the transmit code. The driver is also more
        !            48:  * structured, and I have tried to keep the kernel interface separate
        !            49:  * from the hardware interface (although some routines naturally want
        !            50:  * to do both).
        !            51:  *
        !            52:  * John Sullivan
        !            53:  *
        !            54:  * 18/5/95:
        !            55:  *
        !            56:  * The lock-ups seem to happen when you access card memory after a 586
        !            57:  * reset. This happens only 1 in 12 resets, on a random basis, and
        !            58:  * completely locks the machine. As far as I can see there is no
        !            59:  * workaround possible - the only thing to be done is make sure we
        !            60:  * never reset the card *after* booting the kernel - once at probe time
        !            61:  * must be sufficient, and we'll just have to put up with that failing
        !            62:  * occasionally (or buy a new NIC). By the way, this looks like a 
        !            63:  * definite card bug, since Intel's own driver for DOS does exactly the
        !            64:  * same.
        !            65:  *
        !            66:  * This bug makes switching in and out of promiscuous mode a risky
        !            67:  * business, since we must do a 586 reset each time.
        !            68:  */
        !            69: 
        !            70: /*
        !            71:  * Sources:
        !            72:  *
        !            73:  * The original eexpress.c by Donald Becker
        !            74:  *   Sources: the Crynwr EtherExpress driver source.
        !            75:  *            the Intel Microcommunications Databook Vol.1 1990
        !            76:  *
        !            77:  * wavelan.c and i82586.h
        !            78:  *   This was invaluable for the complete '586 configuration details
        !            79:  *   and command format.
        !            80:  *
        !            81:  * The Crynwr sources (again)
        !            82:  *   Not as useful as the Wavelan driver, but then I had eexpress.c to
        !            83:  *   go off.
        !            84:  *
        !            85:  * The Intel EtherExpress 16 ethernet card
        !            86:  *   Provided the only reason I want to see a working etherexpress driver.
        !            87:  *   A lot of fixes came from just observing how the card (mis)behaves when
        !            88:  *   you prod it.
        !            89:  *
        !            90:  */
        !            91: 
        !            92: static char version[] = 
        !            93: "eexpress.c: v0.10 04-May-95 John Sullivan <[email protected]>\n"
        !            94: "            v0.14 19-May-96 Philip Blundell <[email protected]>\n"
        !            95: "            v0.15 04-Aug-98 Alan Cox <[email protected]>\n";
        !            96: 
        !            97: #include <linux/module.h>
        !            98: 
        !            99: #include <linux/kernel.h>
        !           100: #include <linux/sched.h>
        !           101: #include <linux/types.h>
        !           102: #include <linux/fcntl.h>
        !           103: #include <linux/interrupt.h>
        !           104: #include <linux/ptrace.h>
        !           105: #include <linux/ioport.h>
        !           106: #include <linux/string.h>
        !           107: #include <linux/in.h>
        !           108: #include <asm/system.h>
        !           109: #include <asm/bitops.h>
        !           110: #include <asm/io.h>
        !           111: #include <asm/dma.h>
        !           112: #include <linux/delay.h>
        !           113: #include <linux/errno.h>
        !           114: 
        !           115: #include <linux/netdevice.h>
        !           116: #include <linux/etherdevice.h>
        !           117: #include <linux/skbuff.h>
        !           118: #include <linux/malloc.h>
        !           119: 
        !           120: /*
        !           121:  * Not actually used yet - may be implemented when the driver has
        !           122:  * been debugged!
        !           123:  *
        !           124:  * Debug Level         Driver Status
        !           125:  *     0               Final release
        !           126:  *     1               Beta test
        !           127:  *     2
        !           128:  *     3
        !           129:  *     4               Report timeouts & 586 errors (normal debug level)
        !           130:  *     5               Report all major events
        !           131:  *     6               Dump sent/received packet contents
        !           132:  *     7               Report function entry/exit
        !           133:  */
        !           134: 
        !           135: #ifndef NET_DEBUG
        !           136: #define NET_DEBUG 4
        !           137: #endif
        !           138: static unsigned int net_debug = NET_DEBUG;
        !           139: 
        !           140: #undef F_DEB
        !           141: 
        !           142: #include "eth82586.h"
        !           143: 
        !           144: #define PRIV(x)         ((struct net_local *)(x)->priv)
        !           145: #define EEXP_IO_EXTENT  16
        !           146: 
        !           147: /*
        !           148:  * Private data declarations
        !           149:  */
        !           150: 
        !           151: struct net_local 
        !           152: {
        !           153:        struct enet_statistics stats;
        !           154:        unsigned long init_time;        /* jiffies when eexp_hw_init586 called */
        !           155:        unsigned short rx_first;        /* first rx buf, same as RX_BUF_START */
        !           156:        unsigned short rx_last;         /* last rx buf */
        !           157:        unsigned short tx_head;         /* next free tx buf */
        !           158:        unsigned short tx_reap;         /* first in-use tx buf */
        !           159:        unsigned short tx_tail;         /* previous tx buf to tx_head */
        !           160:        unsigned short tx_link;         /* last known-executing tx buf */
        !           161:        unsigned short last_tx_restart; /* set to tx_link when we restart the CU */
        !           162:        unsigned char started;
        !           163:        unsigned char promisc;
        !           164:        unsigned short rx_buf_start;
        !           165:        unsigned short rx_buf_end;
        !           166:        unsigned short num_tx_bufs;
        !           167:        unsigned short num_rx_bufs;
        !           168: };
        !           169: 
        !           170: unsigned short start_code[] = {
        !           171:        0x0000,                 /* SCP: set bus to 16 bits */
        !           172:        0x0000,0x0000,          /* junk */
        !           173:        0x0000,0x0000,          /* address of ISCP (lo,hi) */
        !           174: 
        !           175:        0x0001,                 /* ISCP: busy - cleared after reset */
        !           176:        0x0008,0x0000,0x0000,   /* offset,address (lo,hi) of SCB */
        !           177: 
        !           178:        0x0000,0x0000,          /* SCB: status, commands */
        !           179:        0x0000,0x0000,          /* links to first command block, first receive descriptor */
        !           180:        0x0000,0x0000,          /* CRC error, alignment error counts */
        !           181:        0x0000,0x0000,          /* out of resources, overrun error counts */
        !           182: 
        !           183:        0x0000,0x0000,          /* pad */
        !           184:        0x0000,0x0000,
        !           185: 
        !           186:        0x0000,Cmd_Config,      /* startup configure sequence, at 0x0020 */
        !           187:        0x0032,                 /* link to next command */
        !           188:        0x080c,                 /* 12 bytes follow : fifo threshold=8 */
        !           189:        0x2e40,                 /* don't rx bad frames : SRDY/ARDY => ext. sync. : preamble len=8
        !           190:                                 * take addresses from data buffers : 6 bytes/address */
        !           191:        0x6000,                 /* default backoff method & priority : interframe spacing = 0x60 */
        !           192:        0xf200,                 /* slot time=0x200 : max collision retry = 0xf */
        !           193:        0x0000,                 /* no HDLC : normal CRC : enable broadcast : disable promiscuous/multicast modes */
        !           194:        0x003c,                 /* minimum frame length = 60 octets) */
        !           195: 
        !           196:        0x0000,Cmd_INT|Cmd_SetAddr,
        !           197:        0x003e,                 /* link to next command */
        !           198:        0x0000,0x0000,0x0000,   /* hardware address placed here, 0x0038 */
        !           199:        0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */
        !           200:        0x003e,
        !           201: 
        !           202:        0x0000
        !           203: 
        !           204: };
        !           205: 
        !           206: #define CONF_LINK 0x0020
        !           207: #define CONF_HW_ADDR 0x0038
        !           208: 
        !           209: /* maps irq number to EtherExpress magic value */
        !           210: static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 };
        !           211: 
        !           212: /*
        !           213:  * Prototypes for Linux interface
        !           214:  */
        !           215: 
        !           216: extern int                  express_probe(struct device *dev);
        !           217: static int                     eexp_open (struct device *dev);
        !           218: static int                     eexp_close(struct device *dev);
        !           219: static struct enet_statistics *eexp_stats(struct device *dev);
        !           220: static int                     eexp_xmit (struct sk_buff *buf, struct device *dev);
        !           221: 
        !           222: static void                    eexp_irq  (int irq, void *dev_addr, struct pt_regs *regs);
        !           223: static void                    eexp_set_multicast(struct device *dev);
        !           224: 
        !           225: /*
        !           226:  * Prototypes for hardware access functions
        !           227:  */
        !           228: 
        !           229: static void           eexp_hw_rx        (struct device *dev);
        !           230: static void           eexp_hw_tx        (struct device *dev, unsigned short *buf, unsigned short len);
        !           231: static int            eexp_hw_probe     (struct device *dev,unsigned short ioaddr);
        !           232: static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, unsigned char location);
        !           233: 
        !           234: static unsigned short eexp_hw_lasttxstat(struct device *dev);
        !           235: static void           eexp_hw_txrestart (struct device *dev);
        !           236: 
        !           237: static void           eexp_hw_txinit    (struct device *dev);
        !           238: static void           eexp_hw_rxinit    (struct device *dev);
        !           239: 
        !           240: static void           eexp_hw_init586   (struct device *dev);
        !           241: static void           eexp_hw_ASICrst   (struct device *dev);
        !           242: 
        !           243: /*
        !           244:  * Linux interface
        !           245:  */
        !           246: 
        !           247: /*
        !           248:  * checks for presence of EtherExpress card
        !           249:  */
        !           250: 
        !           251: int express_probe(struct device *dev)
        !           252: {
        !           253:        unsigned short *port,ports[] = { 0x0300,0x0270,0x0320,0x0340,0 };
        !           254:        unsigned short ioaddr = dev->base_addr;
        !           255: 
        !           256:        if (ioaddr&0xfe00)
        !           257:                return eexp_hw_probe(dev,ioaddr);
        !           258:        else if (ioaddr)
        !           259:                return ENXIO;
        !           260: 
        !           261:        for ( port=&ports[0] ; *port ; port++ ) 
        !           262:        {
        !           263:                unsigned short sum = 0;
        !           264:                int i;
        !           265:                for ( i=0 ; i<4 ; i++ ) 
        !           266:                {
        !           267:                        unsigned short t;
        !           268:                        t = inb(*port + ID_PORT);
        !           269:                        sum |= (t>>4) << ((t & 0x03)<<2);
        !           270:                }
        !           271:                if (sum==0xbaba && !eexp_hw_probe(dev,*port)) 
        !           272:                        return 0;
        !           273:        }
        !           274:        return ENODEV;
        !           275: }
        !           276: 
        !           277: /*
        !           278:  * open and initialize the adapter, ready for use
        !           279:  */
        !           280: 
        !           281: static int eexp_open(struct device *dev)
        !           282: {
        !           283:        int irq = dev->irq;
        !           284:        unsigned short ioaddr = dev->base_addr;
        !           285: 
        !           286: #if NET_DEBUG > 6
        !           287:        printk(KERN_DEBUG "%s: eexp_open()\n", dev->name);
        !           288: #endif
        !           289: 
        !           290:        if (!irq || !irqrmap[irq]) 
        !           291:                return -ENXIO;
        !           292: 
        !           293:        if (irq2dev_map[irq] ||
        !           294:              /* more consistent, surely? */
        !           295:           ((irq2dev_map[irq]=dev),0) ||
        !           296:             request_irq(irq,&eexp_irq,0,"eexpress",NULL)) 
        !           297:                return -EAGAIN;
        !           298: 
        !           299:        request_region(ioaddr, EEXP_IO_EXTENT, "eexpress");
        !           300:        dev->tbusy = 0;
        !           301:        dev->interrupt = 0;
        !           302:        eexp_hw_init586(dev);
        !           303:        dev->start = 1;
        !           304:        MOD_INC_USE_COUNT;
        !           305: #if NET_DEBUG > 6
        !           306:        printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name);
        !           307: #endif
        !           308:        return 0;
        !           309: }
        !           310: 
        !           311: /*
        !           312:  * close and disable the interface, leaving
        !           313:  * the 586 in reset
        !           314:  */
        !           315: static int eexp_close(struct device *dev)
        !           316: {
        !           317:        unsigned short ioaddr = dev->base_addr;
        !           318:        int irq = dev->irq;
        !           319: 
        !           320:        dev->tbusy = 1; 
        !           321:        dev->start = 0;
        !           322:   
        !           323:        outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
        !           324:        PRIV(dev)->started = 0;
        !           325:        outw(SCB_CUsuspend|SCB_RUsuspend,ioaddr+SCB_CMD);
        !           326:        outb(0,ioaddr+SIGNAL_CA);
        !           327:        free_irq(irq,NULL);
        !           328:        irq2dev_map[irq] = NULL;
        !           329:        outb(i586_RST,ioaddr+EEPROM_Ctrl);
        !           330:        release_region(ioaddr,16);
        !           331:        MOD_DEC_USE_COUNT;
        !           332:        return 0;
        !           333: }
        !           334: 
        !           335: /*
        !           336:  * Return interface stats
        !           337:  */
        !           338: 
        !           339: static struct enet_statistics *eexp_stats(struct device *dev)
        !           340: {
        !           341:        struct net_local *lp = (struct net_local *)dev->priv;
        !           342: 
        !           343:        /* 
        !           344:         * Hmmm, this looks a little too easy... The card maintains
        !           345:         * some stats in the SCB, and I'm not convinced we're
        !           346:         * incrementing the most sensible statistics when the card
        !           347:         * returns an error (esp. slow DMA, out-of-resources)
        !           348:         */
        !           349:        return &lp->stats;
        !           350: }
        !           351: 
        !           352: /*
        !           353:  * Called to transmit a packet, or to allow us to right ourselves
        !           354:  * if the kernel thinks we've died.
        !           355:  */
        !           356: 
        !           357: static int eexp_xmit(struct sk_buff *buf, struct device *dev)
        !           358: {
        !           359:        struct net_local *lp = (struct net_local *)dev->priv;
        !           360:        unsigned short ioaddr = dev->base_addr;
        !           361: 
        !           362: #if NET_DEBUG > 6
        !           363:        printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
        !           364: #endif
        !           365: 
        !           366:        outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           367:        if (dev->tbusy) 
        !           368:        {
        !           369:                /* This will happen, but hopefully not as often as when
        !           370:                 * tbusy==0. If it happens too much, we probably ought
        !           371:                 * to think about unwedging ourselves...
        !           372:                 */
        !           373:                if (test_bit(0,(void *)&PRIV(dev)->started)) 
        !           374:                {
        !           375:                        if ((jiffies - dev->trans_start)>5) 
        !           376:                        {
        !           377:                                if (lp->tx_link==lp->last_tx_restart) 
        !           378:                                {
        !           379:                                        unsigned short boguscount=200,rsst;
        !           380:                                        printk(KERN_WARNING "%s: Retransmit timed out, status %04x, resetting...\n",
        !           381:                                                dev->name,inw(ioaddr+SCB_STATUS));
        !           382:                                        eexp_hw_txinit(dev);
        !           383:                                        lp->last_tx_restart = 0;
        !           384:                                        outw(lp->tx_link,ioaddr+SCB_CBL);
        !           385:                                        outw(0,ioaddr+SCB_STATUS);
        !           386:                                        outw(SCB_CUstart,ioaddr+SCB_CMD);
        !           387:                                        outb(0,ioaddr+SIGNAL_CA);
        !           388:                                        while (!SCB_complete(rsst=inw(ioaddr+SCB_STATUS))) 
        !           389:                                        {
        !           390:                                                if (!--boguscount) 
        !           391:                                                {
        !           392:                                                        boguscount=200;
        !           393:                                                        printk(KERN_WARNING "%s: Reset timed out status %04x, retrying...\n",
        !           394:                                                                dev->name,rsst);
        !           395:                                                        outw(lp->tx_link,ioaddr+SCB_CBL);
        !           396:                                                        outw(0,ioaddr+SCB_STATUS);
        !           397:                                                        outw(SCB_CUstart,ioaddr+SCB_CMD);
        !           398:                                                        outb(0,ioaddr+SIGNAL_CA);
        !           399:                                                }
        !           400:                                        }
        !           401:                                        dev->tbusy = 0;
        !           402:                                        mark_bh(NET_BH);
        !           403:                                }
        !           404:                                else
        !           405:                                {
        !           406:                                        unsigned short status = inw(ioaddr+SCB_STATUS);
        !           407:                                        if (SCB_CUdead(status)) 
        !           408:                                        {
        !           409:                                                unsigned short txstatus = eexp_hw_lasttxstat(dev);
        !           410:                                                printk(KERN_WARNING "%s: Transmit timed out, CU not active status %04x %04x, restarting...\n",
        !           411:                                                        dev->name, status, txstatus);
        !           412:                                                eexp_hw_txrestart(dev);
        !           413:                                        }
        !           414:                                        else
        !           415:                                        {
        !           416:                                                unsigned short txstatus = eexp_hw_lasttxstat(dev);
        !           417:                                                if (dev->tbusy && !txstatus) 
        !           418:                                                {
        !           419:                                                        printk(KERN_WARNING "%s: CU wedged, status %04x %04x, resetting...\n",
        !           420:                                                                dev->name,status,txstatus);
        !           421:                                                        eexp_hw_init586(dev); 
        !           422:                                                        dev->tbusy = 0;
        !           423:                                                        mark_bh(NET_BH);
        !           424:                                                }
        !           425:                                        }
        !           426:                                }
        !           427:                        }
        !           428:                }
        !           429:                else
        !           430:                {
        !           431:                        if ((jiffies-lp->init_time)>10)
        !           432:                        {
        !           433:                                unsigned short status = inw(ioaddr+SCB_STATUS);
        !           434:                                printk(KERN_WARNING "%s: i82586 startup timed out, status %04x, resetting...\n",
        !           435:                                        dev->name, status);
        !           436:                                eexp_hw_init586(dev);
        !           437:                                dev->tbusy = 0;
        !           438:                                mark_bh(NET_BH);
        !           439:                        }
        !           440:                }
        !           441:        }
        !           442: 
        !           443:        if (buf==NULL) 
        !           444:        {
        !           445:                unsigned short status = inw(ioaddr+SCB_STATUS);
        !           446:                unsigned short txstatus = eexp_hw_lasttxstat(dev);
        !           447:                if (SCB_CUdead(status)) 
        !           448:                {
        !           449:                        printk(KERN_WARNING "%s: CU has died! status %04x %04x, attempting to restart...\n",
        !           450:                                dev->name, status, txstatus);
        !           451:                        lp->stats.tx_errors++;
        !           452:                        eexp_hw_txrestart(dev);
        !           453:                }
        !           454:                dev_tint(dev);
        !           455:                outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           456:                dev_kfree_skb(buf, FREE_WRITE);
        !           457:                return 0;
        !           458:        }
        !           459: 
        !           460:        if (set_bit(0,(void *)&dev->tbusy)) 
        !           461:        {
        !           462:                lp->stats.tx_dropped++;
        !           463:        }
        !           464:        else
        !           465:        {
        !           466:                unsigned short length = (ETH_ZLEN < buf->len) ? buf->len : ETH_ZLEN;
        !           467:                unsigned short *data = (unsigned short *)buf->data;
        !           468: 
        !           469:                outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           470:                eexp_hw_tx(dev,data,length);
        !           471:                outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           472:        }
        !           473:        dev_kfree_skb(buf, FREE_WRITE);
        !           474:        outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           475:        return 0;
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * Handle an EtherExpress interrupt
        !           480:  * If we've finished initializing, start the RU and CU up.
        !           481:  * If we've already started, reap tx buffers, handle any received packets,
        !           482:  * check to make sure we've not become wedged.
        !           483:  */
        !           484: 
        !           485: static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
        !           486: {
        !           487:        struct device *dev = irq2dev_map[irq];
        !           488:        struct net_local *lp;
        !           489:        unsigned short ioaddr,status,ack_cmd;
        !           490:        unsigned short old_rp,old_wp;
        !           491: 
        !           492:        if (dev==NULL) 
        !           493:        {
        !           494:                printk(KERN_WARNING "net_interrupt(): irq %d for unknown device caught by EExpress\n",irq);
        !           495:                return;
        !           496:        }
        !           497: 
        !           498: #if NET_DEBUG > 6
        !           499:        printk(KERN_DEBUG "%s: interrupt\n", dev->name);
        !           500: #endif
        !           501: 
        !           502:        dev->interrupt = 1; /* should this be reset on exit? */
        !           503:   
        !           504:        lp = (struct net_local *)dev->priv;
        !           505:        ioaddr = dev->base_addr;
        !           506: 
        !           507:        outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
        !           508:        old_rp = inw(ioaddr+READ_PTR);
        !           509:        old_wp = inw(ioaddr+WRITE_PTR);
        !           510:        status = inw(ioaddr+SCB_STATUS);
        !           511:        ack_cmd = SCB_ack(status);
        !           512: 
        !           513:        if (PRIV(dev)->started==0 && SCB_complete(status)) 
        !           514:        {
        !           515: #if NET_DEBUG > 4
        !           516:                printk(KERN_DEBUG "%s: SCBcomplete event received\n", dev->name);
        !           517: #endif
        !           518:                while (SCB_CUstat(status)==2)
        !           519:                        status = inw_p(ioaddr+SCB_STATUS);
        !           520: #if NET_DEBUG > 4
        !           521:                 printk(KERN_DEBUG "%s: CU went non-active (status = %08x)\n", dev->name, status);
        !           522: #endif
        !           523:                PRIV(dev)->started=1;
        !           524:                outw_p(lp->tx_link,ioaddr+SCB_CBL);
        !           525:                outw_p(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA);
        !           526:                ack_cmd |= SCB_CUstart | SCB_RUstart;
        !           527:        }
        !           528:        else if (PRIV(dev)->started) 
        !           529:        {
        !           530:                unsigned short txstatus;
        !           531:                txstatus = eexp_hw_lasttxstat(dev);
        !           532:        }
        !           533:   
        !           534:        if (SCB_rxdframe(status)) 
        !           535:        {
        !           536:                eexp_hw_rx(dev);
        !           537:        }
        !           538: 
        !           539:        if ((PRIV(dev)->started&2)!=0 && SCB_RUstat(status)!=4) 
        !           540:        {
        !           541:                printk(KERN_WARNING "%s: RU stopped status %04x, restarting...\n",
        !           542:                        dev->name,status);
        !           543:                lp->stats.rx_errors++;
        !           544:                eexp_hw_rxinit(dev);
        !           545:                outw(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA);
        !           546:                ack_cmd |= SCB_RUstart;
        !           547:        } 
        !           548:        else if (PRIV(dev)->started==1 && SCB_RUstat(status)==4) 
        !           549:                PRIV(dev)->started|=2;
        !           550: 
        !           551:        outw(ack_cmd,ioaddr+SCB_CMD);
        !           552:        outb(0,ioaddr+SIGNAL_CA);
        !           553:        outw(old_rp,ioaddr+READ_PTR);
        !           554:        outw(old_wp,ioaddr+WRITE_PTR);
        !           555:        outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
        !           556:        dev->interrupt = 0;
        !           557: #if NET_DEBUG > 6
        !           558:         printk(KERN_DEBUG "%s: leaving eexp_irq()\n", dev->name);
        !           559: #endif
        !           560:        return;
        !           561: }
        !           562: 
        !           563: /*
        !           564:  * Hardware access functions
        !           565:  */
        !           566: 
        !           567: /*
        !           568:  * Check all the receive buffers, and hand any received packets
        !           569:  * to the upper levels. Basic sanity check on each frame
        !           570:  * descriptor
        !           571:  */
        !           572:  
        !           573: static void eexp_hw_rx(struct device *dev)
        !           574: {
        !           575:        struct net_local *lp = (struct net_local *)dev->priv;
        !           576:        unsigned short ioaddr = dev->base_addr;
        !           577:        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        !           578:        unsigned short old_rp = inw(ioaddr+READ_PTR);
        !           579:        unsigned short rx_block = lp->rx_first;
        !           580:        unsigned short boguscount = lp->num_rx_bufs;
        !           581: 
        !           582: #if NET_DEBUG > 6
        !           583:        printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name);
        !           584: #endif
        !           585: 
        !           586:        while (outw(rx_block,ioaddr+READ_PTR),boguscount--) 
        !           587:        {
        !           588:                unsigned short status = inw(ioaddr);
        !           589:                unsigned short rfd_cmd = inw(ioaddr);
        !           590:                unsigned short rx_next = inw(ioaddr);
        !           591:                unsigned short pbuf = inw(ioaddr);
        !           592:                unsigned short pkt_len;
        !           593: 
        !           594:                if (FD_Done(status)) 
        !           595:                {
        !           596:                        outw(pbuf,ioaddr+READ_PTR);
        !           597:                        pkt_len = inw(ioaddr);
        !           598: 
        !           599:                        if (rfd_cmd!=0x0000 || pbuf!=rx_block+0x16
        !           600:                                || (pkt_len & 0xc000)!=0xc000) 
        !           601:                        {
        !           602:                                printk(KERN_WARNING "%s: Rx frame at %04x corrupted, status %04x, cmd %04x, "
        !           603:                                        "next %04x, pbuf %04x, len %04x\n",dev->name,rx_block,
        !           604:                                        status,rfd_cmd,rx_next,pbuf,pkt_len);
        !           605:                                boguscount++;
        !           606:                                continue;
        !           607:                        }
        !           608:                        else if (!FD_OK(status)) 
        !           609:                        {
        !           610:                                lp->stats.rx_errors++;
        !           611:                                if (FD_CRC(status)) 
        !           612:                                        lp->stats.rx_crc_errors++;
        !           613:                                if (FD_Align(status))
        !           614:                                        lp->stats.rx_frame_errors++;
        !           615:                                if (FD_Resrc(status))
        !           616:                                        lp->stats.rx_fifo_errors++;
        !           617:                                if (FD_DMA(status))
        !           618:                                        lp->stats.rx_over_errors++;
        !           619:                                if (FD_Short(status))
        !           620:                                        lp->stats.rx_length_errors++;
        !           621:                        }
        !           622:                        else
        !           623:                        {
        !           624:                                struct sk_buff *skb;
        !           625:                                pkt_len &= 0x3fff;
        !           626:                                skb = dev_alloc_skb(pkt_len+16);
        !           627:                                if (skb == NULL) 
        !           628:                                {
        !           629:                                        printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name);
        !           630:                                        lp->stats.rx_dropped++;
        !           631:                                        break;
        !           632:                                }
        !           633:                                skb->dev = dev;
        !           634:                                skb_reserve(skb, 2);
        !           635:                                outw(pbuf+10,ioaddr+READ_PTR);
        !           636:                                insw(ioaddr,skb_put(skb,pkt_len),(pkt_len+1)>>1);
        !           637:                                skb->protocol = eth_type_trans(skb,dev);
        !           638:                                netif_rx(skb);
        !           639:                                lp->stats.rx_packets++;
        !           640:                        }
        !           641:                        outw(rx_block,ioaddr+WRITE_PTR);
        !           642:                        outw(0x0000,ioaddr);
        !           643:                        outw(0x0000,ioaddr);
        !           644:                }
        !           645:                rx_block = rx_next;
        !           646:        }
        !           647:        outw(old_rp,ioaddr+READ_PTR);
        !           648:        outw(old_wp,ioaddr+WRITE_PTR);
        !           649: }
        !           650: 
        !           651: /*
        !           652:  * Hand a packet to the card for transmission
        !           653:  * If we get here, we MUST have already checked
        !           654:  * to make sure there is room in the transmit
        !           655:  * buffer region
        !           656:  */
        !           657: 
        !           658: static void eexp_hw_tx(struct device *dev, unsigned short *buf, unsigned short len)
        !           659: {
        !           660:        struct net_local *lp = (struct net_local *)dev->priv;
        !           661:        unsigned short ioaddr = dev->base_addr;
        !           662:        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        !           663: 
        !           664:        outw(lp->tx_head,ioaddr+WRITE_PTR);
        !           665:        outw(0x0000,ioaddr);
        !           666:        outw(Cmd_INT|Cmd_Xmit,ioaddr);
        !           667:        outw(lp->tx_head+0x08,ioaddr);
        !           668:        outw(lp->tx_head+0x0e,ioaddr);
        !           669:        outw(0x0000,ioaddr);
        !           670:        outw(0x0000,ioaddr);
        !           671:        outw(lp->tx_head+0x08,ioaddr);
        !           672:        outw(0x8000|len,ioaddr);
        !           673:        outw(-1,ioaddr);
        !           674:        outw(lp->tx_head+0x16,ioaddr);
        !           675:        outw(0,ioaddr);
        !           676:        outsw(ioaddr,buf,(len+1)>>1);
        !           677:        outw(lp->tx_tail+0x0c,ioaddr+WRITE_PTR);
        !           678:        outw(lp->tx_head,ioaddr);
        !           679:        dev->trans_start = jiffies;
        !           680:        lp->tx_tail = lp->tx_head;
        !           681:        if (lp->tx_head==TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) 
        !           682:                lp->tx_head = TX_BUF_START;
        !           683:        else 
        !           684:                lp->tx_head += TX_BUF_SIZE;
        !           685:        if (lp->tx_head != lp->tx_reap) 
        !           686:                dev->tbusy = 0;
        !           687:        outw(old_wp,ioaddr+WRITE_PTR);
        !           688: }
        !           689: 
        !           690: /*
        !           691:  * Sanity check the suspected EtherExpress card
        !           692:  * Read hardware address, reset card, size memory and
        !           693:  * initialize buffer memory pointers. These should
        !           694:  * probably be held in dev->priv, in case someone has 2
        !           695:  * differently configured cards in their box (Arghhh!)
        !           696:  */
        !           697: 
        !           698: static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
        !           699: {
        !           700:        unsigned short hw_addr[3];
        !           701:        int i;
        !           702:        unsigned char *chw_addr = (unsigned char *)hw_addr;
        !           703: 
        !           704:        printk("%s: EtherExpress at %#x, ",dev->name,ioaddr);
        !           705: 
        !           706:        hw_addr[0] = eexp_hw_readeeprom(ioaddr,2);
        !           707:        hw_addr[1] = eexp_hw_readeeprom(ioaddr,3);
        !           708:        hw_addr[2] = eexp_hw_readeeprom(ioaddr,4);
        !           709: 
        !           710:        /* Standard Address or Compaq LTE Address */
        !           711:        if (!((hw_addr[2]==0x00aa && ((hw_addr[1] & 0xff00)==0x0000)) ||
        !           712:              (hw_addr[2]==0x0080 && ((hw_addr[1] & 0xff00)==0x5F00)))) 
        !           713:        {
        !           714:                printk("rejected: invalid address %04x%04x%04x\n",
        !           715:                        hw_addr[2],hw_addr[1],hw_addr[0]);
        !           716:                return -ENODEV;
        !           717:        }
        !           718: 
        !           719:        dev->base_addr = ioaddr;
        !           720:        for ( i=0 ; i<6 ; i++ ) 
        !           721:                dev->dev_addr[i] = chw_addr[5-i];
        !           722: 
        !           723:        {
        !           724:                char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
        !           725:                char *ifmap[]={"AUI", "BNC", "10baseT"};
        !           726:                enum iftype {AUI=0, BNC=1, TP=2};
        !           727:                unsigned short setupval = eexp_hw_readeeprom(ioaddr,0);
        !           728: 
        !           729:                dev->irq = irqmap[setupval>>13];
        !           730:                dev->if_port = !(setupval & 0x1000) ? AUI :
        !           731:                        eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TP : BNC;
        !           732: 
        !           733:                printk("IRQ %d, Interface %s, ",dev->irq,ifmap[dev->if_port]);
        !           734: 
        !           735:                outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !           736:                outb(0,ioaddr+SET_IRQ);
        !           737:        }
        !           738: 
        !           739:        dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
        !           740:        if (!dev->priv) 
        !           741:                return -ENOMEM;
        !           742: 
        !           743:        memset(dev->priv, 0, sizeof(struct net_local));
        !           744: 
        !           745:        eexp_hw_ASICrst(dev);
        !           746: 
        !           747:        {
        !           748:                unsigned short i586mso = 0x023e;
        !           749:                unsigned short old_wp,old_rp,old_a0,old_a1;
        !           750:                unsigned short a0_0,a1_0,a0_1,a1_1;
        !           751: 
        !           752:                old_wp = inw(ioaddr+WRITE_PTR);
        !           753:                old_rp = inw(ioaddr+READ_PTR);
        !           754:                outw(0x8000+i586mso,ioaddr+READ_PTR);
        !           755:                old_a1 = inw(ioaddr);
        !           756:                outw(i586mso,ioaddr+READ_PTR);
        !           757:                old_a0 = inw(ioaddr);
        !           758:                outw(i586mso,ioaddr+WRITE_PTR);
        !           759:                outw(0x55aa,ioaddr);
        !           760:                outw(i586mso,ioaddr+READ_PTR);
        !           761:                a0_0 = inw(ioaddr);
        !           762:                outw(0x8000+i586mso,ioaddr+WRITE_PTR);
        !           763:                outw(0x5a5a,ioaddr);
        !           764:                outw(0x8000+i586mso,ioaddr+READ_PTR);
        !           765:                a1_0 = inw(ioaddr);
        !           766:                outw(i586mso,ioaddr+READ_PTR);
        !           767:                a0_1 = inw(ioaddr);
        !           768:                outw(i586mso,ioaddr+WRITE_PTR);
        !           769:                outw(0x1234,ioaddr);
        !           770:                outw(0x8000+i586mso,ioaddr+READ_PTR);
        !           771:                a1_1 = inw(ioaddr);
        !           772: 
        !           773:                if ((a0_0 != a0_1) || (a1_0 != a1_1) ||
        !           774:                        (a1_0 != 0x5a5a) || (a0_0 != 0x55aa)) 
        !           775:                {
        !           776:                        printk("32k\n");
        !           777:                        PRIV(dev)->rx_buf_end = 0x7ff6;
        !           778:                        PRIV(dev)->num_tx_bufs = 4;
        !           779:                }
        !           780:                else
        !           781:                {
        !           782:                        printk("64k\n");
        !           783:                        PRIV(dev)->num_tx_bufs = 8;
        !           784:                        PRIV(dev)->rx_buf_start = TX_BUF_START + (PRIV(dev)->num_tx_bufs*TX_BUF_SIZE);
        !           785:                        PRIV(dev)->rx_buf_end = 0xfff6;
        !           786:                }
        !           787: 
        !           788:                outw(0x8000+i586mso,ioaddr+WRITE_PTR);
        !           789:                outw(old_a1,ioaddr);
        !           790:                outw(i586mso,ioaddr+WRITE_PTR);
        !           791:                outw(old_a0,ioaddr);
        !           792:                outw(old_wp,ioaddr+WRITE_PTR);
        !           793:                outw(old_rp,ioaddr+READ_PTR);
        !           794:        }
        !           795:   
        !           796:        if (net_debug) 
        !           797:                printk(version);
        !           798:        dev->open = eexp_open;
        !           799:        dev->stop = eexp_close;
        !           800:        dev->hard_start_xmit = eexp_xmit;
        !           801:        dev->get_stats = eexp_stats;
        !           802:        dev->set_multicast_list = &eexp_set_multicast;
        !           803:        ether_setup(dev);
        !           804:        return 0;
        !           805: }
        !           806: 
        !           807: /*
        !           808:  *     Read a word from eeprom location (0-63?)
        !           809:  */
        !           810: static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, unsigned char location)
        !           811: {
        !           812:        unsigned short cmd = 0x180|(location&0x7f);
        !           813:        unsigned short rval = 0,wval = EC_CS|i586_RST;
        !           814:        int i;
        !           815:  
        !           816:        outb(EC_CS|i586_RST,ioaddr+EEPROM_Ctrl);
        !           817:        for ( i=0x100 ; i ; i>>=1 ) 
        !           818:        {
        !           819:                if (cmd&i) 
        !           820:                        wval |= EC_Wr;
        !           821:                else 
        !           822:                        wval &= ~EC_Wr;
        !           823: 
        !           824:                outb(wval,ioaddr+EEPROM_Ctrl);
        !           825:                outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
        !           826:                eeprom_delay();
        !           827:                outb(wval,ioaddr+EEPROM_Ctrl);
        !           828:                eeprom_delay();
        !           829:        }       
        !           830:        wval &= ~EC_Wr;
        !           831:        outb(wval,ioaddr+EEPROM_Ctrl);
        !           832:        for ( i=0x8000 ; i ; i>>=1 ) 
        !           833:        {
        !           834:                outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
        !           835:                eeprom_delay();
        !           836:                if (inb(ioaddr+EEPROM_Ctrl)&EC_Rd) 
        !           837:                        rval |= i;
        !           838:                outb(wval,ioaddr+EEPROM_Ctrl);
        !           839:                eeprom_delay();
        !           840:        }
        !           841:        wval &= ~EC_CS;
        !           842:        outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl);
        !           843:        eeprom_delay();
        !           844:        outb(wval,ioaddr+EEPROM_Ctrl);
        !           845:        eeprom_delay();
        !           846:        return rval;
        !           847: }
        !           848: 
        !           849: /*
        !           850:  * Reap tx buffers and return last transmit status.
        !           851:  * if ==0 then either:
        !           852:  *    a) we're not transmitting anything, so why are we here?
        !           853:  *    b) we've died.
        !           854:  * otherwise, Stat_Busy(return) means we've still got some packets
        !           855:  * to transmit, Stat_Done(return) means our buffers should be empty
        !           856:  * again
        !           857:  */
        !           858: 
        !           859: static unsigned short eexp_hw_lasttxstat(struct device *dev)
        !           860: {
        !           861:        struct net_local *lp = (struct net_local *)dev->priv;
        !           862:        unsigned short ioaddr = dev->base_addr;
        !           863:        unsigned short old_rp = inw(ioaddr+READ_PTR);
        !           864:        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        !           865:        unsigned short tx_block = lp->tx_reap;
        !           866:        unsigned short status;
        !           867:   
        !           868:        if (!test_bit(0,(void *)&dev->tbusy) && lp->tx_head==lp->tx_reap) 
        !           869:                return 0x0000;
        !           870: 
        !           871:        do
        !           872:        {
        !           873:                outw(tx_block,ioaddr+READ_PTR);
        !           874:                status = inw(ioaddr);
        !           875:                if (!Stat_Done(status)) 
        !           876:                {
        !           877:                        lp->tx_link = tx_block;
        !           878:                        outw(old_rp,ioaddr+READ_PTR);
        !           879:                        outw(old_wp,ioaddr+WRITE_PTR);
        !           880:                        return status;
        !           881:                }
        !           882:                else 
        !           883:                {
        !           884:                        lp->last_tx_restart = 0;
        !           885:                        lp->stats.collisions += Stat_NoColl(status);
        !           886:                        if (!Stat_OK(status)) 
        !           887:                        {
        !           888:                                if (Stat_Abort(status)) 
        !           889:                                        lp->stats.tx_aborted_errors++;
        !           890:                                if (Stat_TNoCar(status) || Stat_TNoCTS(status)) 
        !           891:                                        lp->stats.tx_carrier_errors++;
        !           892:                                if (Stat_TNoDMA(status)) 
        !           893:                                        lp->stats.tx_fifo_errors++;
        !           894:                        }
        !           895:                        else
        !           896:                                lp->stats.tx_packets++;
        !           897:                }
        !           898:                if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) 
        !           899:                        lp->tx_reap = tx_block = TX_BUF_START;
        !           900:                else
        !           901:                        lp->tx_reap = tx_block += TX_BUF_SIZE;
        !           902:                dev->tbusy = 0;
        !           903:                mark_bh(NET_BH);
        !           904:        }
        !           905:        while (lp->tx_reap != lp->tx_head);
        !           906: 
        !           907:        lp->tx_link = lp->tx_tail + 0x08;
        !           908:        outw(old_rp,ioaddr+READ_PTR);
        !           909:        outw(old_wp,ioaddr+WRITE_PTR);
        !           910: 
        !           911:        return status;
        !           912: }
        !           913: 
        !           914: /* 
        !           915:  * This should never happen. It is called when some higher
        !           916:  * routine detects the CU has stopped, to try to restart
        !           917:  * it from the last packet we knew we were working on,
        !           918:  * or the idle loop if we had finished for the time.
        !           919:  */
        !           920: 
        !           921: static void eexp_hw_txrestart(struct device *dev)
        !           922: {
        !           923:        struct net_local *lp = (struct net_local *)dev->priv;
        !           924:        unsigned short ioaddr = dev->base_addr;
        !           925:   
        !           926:        lp->last_tx_restart = lp->tx_link;
        !           927:        outw(lp->tx_link,ioaddr+SCB_CBL);
        !           928:        outw(SCB_CUstart,ioaddr+SCB_CMD);
        !           929:        outw(0,ioaddr+SCB_STATUS);
        !           930:        outb(0,ioaddr+SIGNAL_CA);
        !           931: 
        !           932:        {
        !           933:                unsigned short boguscount=50,failcount=5;
        !           934:                while (!inw(ioaddr+SCB_STATUS)) 
        !           935:                {
        !           936:                        if (!--boguscount) 
        !           937:                        {
        !           938:                                if (--failcount) 
        !           939:                                {
        !           940:                                        printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n",
        !           941:                                                dev->name, inw(ioaddr+SCB_STATUS), inw(ioaddr+SCB_CMD));
        !           942:                                        outw(lp->tx_link,ioaddr+SCB_CBL);
        !           943:                                        outw(0,ioaddr+SCB_STATUS);
        !           944:                                        outw(SCB_CUstart,ioaddr+SCB_CMD);
        !           945:                                        outb(0,ioaddr+SIGNAL_CA);
        !           946:                                        boguscount = 100;
        !           947:                                }
        !           948:                                else
        !           949:                                {
        !           950:                                        printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name);
        !           951:                                        eexp_hw_init586(dev);
        !           952:                                        dev->tbusy = 0;
        !           953:                                        mark_bh(NET_BH);
        !           954:                                        return;
        !           955:                                }
        !           956:                        }
        !           957:                }
        !           958:        }
        !           959: }
        !           960: 
        !           961: /*
        !           962:  * Writes down the list of transmit buffers into card
        !           963:  * memory. Initial separate, repeated transmits link
        !           964:  * them into a circular list, such that the CU can
        !           965:  * be constantly active, and unlink them as we reap
        !           966:  * transmitted packet buffers, so the CU doesn't loop
        !           967:  * and endlessly transmit packets. (Try hacking the driver
        !           968:  * to send continuous broadcast messages, say ARP requests
        !           969:  * on a subnet with Windows boxes running on Novell and
        !           970:  * LAN Workplace with EMM386. Amusing to watch them all die
        !           971:  * horribly leaving the Linux boxes up!)
        !           972:  */
        !           973: 
        !           974: static void eexp_hw_txinit(struct device *dev)
        !           975: {
        !           976:        struct net_local *lp = (struct net_local *)dev->priv;
        !           977:        unsigned short ioaddr = dev->base_addr;
        !           978:        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        !           979:        unsigned short tx_block = TX_BUF_START;
        !           980:        unsigned short curtbuf;
        !           981: 
        !           982:        for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ ) 
        !           983:        {
        !           984:                outw(tx_block,ioaddr+WRITE_PTR);
        !           985:                outw(0x0000,ioaddr);
        !           986:                outw(Cmd_INT|Cmd_Xmit,ioaddr);
        !           987:                outw(tx_block+0x08,ioaddr);
        !           988:                outw(tx_block+0x0e,ioaddr);
        !           989:                outw(0x0000,ioaddr);
        !           990:                outw(0x0000,ioaddr);
        !           991:                outw(tx_block+0x08,ioaddr);
        !           992:                outw(0x8000,ioaddr);
        !           993:                outw(-1,ioaddr);
        !           994:                outw(tx_block+0x16,ioaddr);
        !           995:                outw(0x0000,ioaddr);
        !           996:                tx_block += TX_BUF_SIZE;
        !           997:        }
        !           998:        lp->tx_head = TX_BUF_START;
        !           999:        lp->tx_reap = TX_BUF_START;
        !          1000:        lp->tx_tail = tx_block - TX_BUF_SIZE;
        !          1001:        lp->tx_link = lp->tx_tail + 0x08;
        !          1002:        lp->rx_buf_start = tx_block;
        !          1003:        outw(old_wp,ioaddr+WRITE_PTR);
        !          1004: }
        !          1005: 
        !          1006: /* is this a standard test pattern, or dbecker randomness? */
        !          1007: 
        !          1008: unsigned short rx_words[] = 
        !          1009: {
        !          1010:        0xfeed,0xf00d,0xf001,0x0505,0x2424,0x6565,0xdeaf
        !          1011: };
        !          1012: 
        !          1013: /*
        !          1014:  * Write the circular list of receive buffer descriptors to
        !          1015:  * card memory. Note, we no longer mark the end of the list,
        !          1016:  * so if all the buffers fill up, the 82586 will loop until
        !          1017:  * we free one. This may sound dodgy, but it works, and
        !          1018:  * it makes the error detection in the interrupt handler
        !          1019:  * a lot simpler.
        !          1020:  */
        !          1021: 
        !          1022: static void eexp_hw_rxinit(struct device *dev)
        !          1023: {
        !          1024:        struct net_local *lp = (struct net_local *)dev->priv;
        !          1025:        unsigned short ioaddr = dev->base_addr;
        !          1026:        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        !          1027:        unsigned short rx_block = lp->rx_buf_start;
        !          1028: 
        !          1029:        lp->num_rx_bufs = 0;
        !          1030:        lp->rx_first = rx_block;
        !          1031:        do 
        !          1032:        {
        !          1033:                lp->num_rx_bufs++;
        !          1034:                outw(rx_block,ioaddr+WRITE_PTR);
        !          1035:                outw(0x0000,ioaddr);
        !          1036:                outw(0x0000,ioaddr);
        !          1037:                outw(rx_block+RX_BUF_SIZE,ioaddr);
        !          1038:                outw(rx_block+0x16,ioaddr);
        !          1039:                outsw(ioaddr, rx_words, sizeof(rx_words)>>1);
        !          1040:                outw(0x8000,ioaddr);
        !          1041:                outw(-1,ioaddr);
        !          1042:                outw(rx_block+0x20,ioaddr);
        !          1043:                outw(0x0000,ioaddr);
        !          1044:                outw(0x8000|(RX_BUF_SIZE-0x20),ioaddr);
        !          1045:                lp->rx_last = rx_block;
        !          1046:                rx_block += RX_BUF_SIZE;
        !          1047:        } while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);
        !          1048: 
        !          1049:        outw(lp->rx_last+4,ioaddr+WRITE_PTR);
        !          1050:        outw(lp->rx_first,ioaddr);
        !          1051: 
        !          1052:        outw(old_wp,ioaddr+WRITE_PTR);
        !          1053: }
        !          1054: 
        !          1055: /*
        !          1056:  * Reset the 586, fill memory (including calls to
        !          1057:  * eexp_hw_[(rx)(tx)]init()) unreset, and start
        !          1058:  * the configuration sequence. We don't wait for this
        !          1059:  * to finish, but allow the interrupt handler to start
        !          1060:  * the CU and RU for us. We can't start the receive/
        !          1061:  * transmission system up before we know that the
        !          1062:  * hardware is configured correctly
        !          1063:  */
        !          1064: static void eexp_hw_init586(struct device *dev)
        !          1065: {
        !          1066:        struct net_local *lp = (struct net_local *)dev->priv;
        !          1067:        unsigned short ioaddr = dev->base_addr;
        !          1068: 
        !          1069: #if NET_DEBUG > 6
        !          1070:         printk("%s: eexp_hw_init586()\n", dev->name);
        !          1071: #endif
        !          1072: 
        !          1073:        lp->started = 0;
        !          1074:        set_loopback;
        !          1075: 
        !          1076:        outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !          1077:        outb_p(i586_RST,ioaddr+EEPROM_Ctrl);
        !          1078:        udelay(2000);  /* delay 20ms */
        !          1079:         {
        !          1080:                unsigned long ofs;
        !          1081:                for (ofs = 0; ofs < lp->rx_buf_end; ofs += 32) {
        !          1082:                        unsigned long i;
        !          1083:                        outw_p(ofs, ioaddr+SM_PTR);
        !          1084:                        for (i = 0; i < 16; i++) {
        !          1085:                                outw_p(0, ioaddr+SM_ADDR(i<<1));
        !          1086:                        }
        !          1087:                }
        !          1088:        }
        !          1089: 
        !          1090:        outw_p(lp->rx_buf_end,ioaddr+WRITE_PTR);
        !          1091:        start_code[28] = (dev->flags & IFF_PROMISC)?(start_code[28] | 1):(start_code[28] & ~1);
        !          1092:        lp->promisc = dev->flags & IFF_PROMISC;
        !          1093:        /* We may die here */
        !          1094:        outsw(ioaddr, start_code, sizeof(start_code)>>1);
        !          1095:        outw(CONF_HW_ADDR,ioaddr+WRITE_PTR);
        !          1096:        outsw(ioaddr,dev->dev_addr,3);
        !          1097:        eexp_hw_txinit(dev);
        !          1098:        eexp_hw_rxinit(dev);
        !          1099:        outw(0,ioaddr+WRITE_PTR);
        !          1100:        outw(1,ioaddr);
        !          1101:        outb(0,ioaddr+EEPROM_Ctrl);
        !          1102:        outw(0,ioaddr+SCB_CMD);
        !          1103:        outb(0,ioaddr+SIGNAL_CA);
        !          1104:        {
        !          1105:                unsigned short rboguscount=50,rfailcount=5;
        !          1106:                while (outw(0,ioaddr+READ_PTR),inw(ioaddr)) 
        !          1107:                {
        !          1108:                        if (!--rboguscount) 
        !          1109:                        {
        !          1110:                                printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n",
        !          1111:                                        dev->name);
        !          1112:                                outw(0,ioaddr+SCB_CMD);
        !          1113:                                outb(0,ioaddr+SIGNAL_CA);
        !          1114:                                rboguscount = 100;
        !          1115:                                if (!--rfailcount) 
        !          1116:                                {
        !          1117:                                        printk(KERN_WARNING "%s: i82586 not responding, giving up.\n",
        !          1118:                                                dev->name);
        !          1119:                                        return;
        !          1120:                                }
        !          1121:                        }
        !          1122:                }
        !          1123:        }
        !          1124: 
        !          1125:        outw(CONF_LINK,ioaddr+SCB_CBL);
        !          1126:        outw(0,ioaddr+SCB_STATUS);
        !          1127:        outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD);
        !          1128:        outb(0,ioaddr+SIGNAL_CA);
        !          1129:        {
        !          1130:                unsigned short iboguscount=50,ifailcount=5;
        !          1131:                while (!inw(ioaddr+SCB_STATUS)) 
        !          1132:                {
        !          1133:                        if (!--iboguscount) 
        !          1134:                        {
        !          1135:                                if (--ifailcount) 
        !          1136:                                {
        !          1137:                                        printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n",
        !          1138:                                                dev->name, inw(ioaddr+SCB_STATUS), inw(ioaddr+SCB_CMD));
        !          1139:                                        outw(CONF_LINK,ioaddr+SCB_CBL);
        !          1140:                                        outw(0,ioaddr+SCB_STATUS);
        !          1141:                                        outw(0xf000|SCB_CUstart,ioaddr+SCB_CMD);
        !          1142:                                        outb(0,ioaddr+SIGNAL_CA);
        !          1143:                                        iboguscount = 100;
        !          1144:                                }
        !          1145:                                else 
        !          1146:                                {
        !          1147:                                        printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name);
        !          1148:                                        return;
        !          1149:                                }
        !          1150:                        }
        !          1151:                }
        !          1152:        }
        !          1153:   
        !          1154:        outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !          1155:        clear_loopback;
        !          1156:        lp->init_time = jiffies;
        !          1157: #if NET_DEBUG > 6
        !          1158:         printk("%s: leaving eexp_hw_init586()\n", dev->name);
        !          1159: #endif
        !          1160:        return;
        !          1161: }
        !          1162: 
        !          1163: /* 
        !          1164:  * completely reset the EtherExpress hardware. We will most likely get
        !          1165:  * an interrupt during this whether we want one or not. It is best,
        !          1166:  * therefore, to call this while we don't have a request_irq() on.
        !          1167:  */
        !          1168: 
        !          1169: static void eexp_hw_ASICrst(struct device *dev)
        !          1170: {
        !          1171:        unsigned short ioaddr = dev->base_addr;
        !          1172:        unsigned short wrval = 0x0001,succount=0,boguscount=500;
        !          1173: 
        !          1174:        outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
        !          1175: 
        !          1176:        PRIV(dev)->started = 0;
        !          1177:        outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl);
        !          1178:        while (succount<20) 
        !          1179:        {
        !          1180:                if (wrval == 0xffff) 
        !          1181:                        wrval = 0x0001;
        !          1182:                outw(0,ioaddr+WRITE_PTR);
        !          1183:                outw(wrval,ioaddr);
        !          1184:                outw(0,ioaddr+READ_PTR);
        !          1185:                if (wrval++ == inw(ioaddr)) 
        !          1186:                        succount++;
        !          1187:                else 
        !          1188:                {
        !          1189:                        succount = 0;
        !          1190:                        if (!boguscount--) 
        !          1191:                        {
        !          1192:                                boguscount = 500;
        !          1193:                                printk("%s: Having problems resetting EtherExpress ASIC, continuing...\n",
        !          1194:                                        dev->name);
        !          1195:                                wrval = 0x0001;
        !          1196:                                outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl);
        !          1197:                        }
        !          1198:                }
        !          1199:        }
        !          1200:        outb(i586_RST,ioaddr+EEPROM_Ctrl);
        !          1201: }
        !          1202: 
        !          1203: 
        !          1204: /*
        !          1205:  * Set or clear the multicast filter for this adaptor.
        !          1206:  * We have to do a complete 586 restart for this to take effect.
        !          1207:  * At the moment only promiscuous mode is supported.
        !          1208:  */
        !          1209: static void
        !          1210: eexp_set_multicast(struct device *dev)
        !          1211: {
        !          1212:        if ((dev->flags & IFF_PROMISC) != PRIV(dev)->promisc)
        !          1213:                eexp_hw_init586(dev);
        !          1214: }
        !          1215: 
        !          1216: 
        !          1217: /*
        !          1218:  * MODULE stuff
        !          1219:  */
        !          1220: #ifdef MODULE
        !          1221: 
        !          1222: #define EEXP_MAX_CARDS     4    /* max number of cards to support */
        !          1223: #define NAMELEN            8    /* max length of dev->name (inc null) */
        !          1224: 
        !          1225: static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, };
        !          1226: 
        !          1227: static struct device dev_eexp[EEXP_MAX_CARDS] = 
        !          1228: {
        !          1229:         { NULL,         /* will allocate dynamically */
        !          1230:          0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },  
        !          1231: };
        !          1232: 
        !          1233: int irq[EEXP_MAX_CARDS] = {0, };
        !          1234: int io[EEXP_MAX_CARDS] = {0, };
        !          1235: 
        !          1236: /* Ideally the user would give us io=, irq= for every card.  If any parameters
        !          1237:  * are specified, we verify and then use them.  If no parameters are given, we
        !          1238:  * autoprobe for one card only.
        !          1239:  */
        !          1240: int init_module(void)
        !          1241: {
        !          1242:        int this_dev, found = 0;
        !          1243: 
        !          1244:        for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
        !          1245:                struct device *dev = &dev_eexp[this_dev];
        !          1246:                dev->name = namelist + (NAMELEN*this_dev);
        !          1247:                dev->irq = irq[this_dev];
        !          1248:                dev->base_addr = io[this_dev];
        !          1249:                if (io[this_dev] == 0) {
        !          1250:                        if (this_dev) break;
        !          1251:                        printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
        !          1252:                }
        !          1253:                if (register_netdev(dev) != 0) {
        !          1254:                        printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]);
        !          1255:                        if (found != 0) return 0;
        !          1256:                        return -ENXIO;
        !          1257:                }
        !          1258:                found++;
        !          1259:        }
        !          1260:        return 0;
        !          1261: }
        !          1262: 
        !          1263: void cleanup_module(void)
        !          1264: {
        !          1265:        int this_dev;
        !          1266:         
        !          1267:        for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
        !          1268:                struct device *dev = &dev_eexp[this_dev];
        !          1269:                if (dev->priv != NULL) {
        !          1270:                        kfree(dev->priv);
        !          1271:                        dev->priv = NULL;
        !          1272:                        release_region(dev->base_addr, EEXP_IO_EXTENT);
        !          1273:                        unregister_netdev(dev);
        !          1274:                }
        !          1275:        }
        !          1276: }
        !          1277: #endif
        !          1278: 
        !          1279: /*
        !          1280:  * Local Variables:
        !          1281:  *  c-file-style: "linux"
        !          1282:  *  tab-width: 8
        !          1283:  *  compile-command: "gcc -D__KERNEL__ -I/discs/bibble/src/linux-1.3.69/include  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE  -c 3c505.c"
        !          1284:  * End:
        !          1285:  */

unix.superglobalmegacorp.com

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