|
|
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: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.