|
|
1.1 ! root 1: /* eexpress.c: Intel EtherExpress device driver for Linux. */ ! 2: /* ! 3: Written 1993 by Donald Becker. ! 4: Copyright 1993 United States Government as represented by the Director, ! 5: National Security Agency. This software may only be used and distributed ! 6: according to the terms of the GNU Public License as modified by SRC, ! 7: incorporated herein by reference. ! 8: ! 9: The author may be reached as [email protected] or ! 10: C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 ! 11: ! 12: Things remaining to do: ! 13: Check that the 586 and ASIC are reset/unreset at the right times. ! 14: Check tx and rx buffer setup. ! 15: The current Tx is single-buffer-only. ! 16: Move the theory of operation and memory map documentation. ! 17: Rework the board error reset ! 18: The statistics need to be updated correctly. ! 19: ! 20: Modularized by Pauline Middelink <[email protected]> ! 21: Changed to support io= irq= by Alan Cox <[email protected]> ! 22: */ ! 23: ! 24: static const char *version = ! 25: "eexpress.c:v0.07 1/19/94 Donald Becker ([email protected])\n"; ! 26: ! 27: /* ! 28: Sources: ! 29: This driver wouldn't have been written with the availability of the ! 30: Crynwr driver source code. It provided a known-working implementation ! 31: that filled in the gaping holes of the Intel documentation. Three cheers ! 32: for Russ Nelson. ! 33: ! 34: Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough ! 35: info that the casual reader might think that it documents the i82586. ! 36: */ ! 37: ! 38: #include <linux/module.h> ! 39: ! 40: #include <linux/kernel.h> ! 41: #include <linux/sched.h> ! 42: #include <linux/types.h> ! 43: #include <linux/fcntl.h> ! 44: #include <linux/interrupt.h> ! 45: #include <linux/ptrace.h> ! 46: #include <linux/ioport.h> ! 47: #include <linux/string.h> ! 48: #include <linux/in.h> ! 49: #include <asm/system.h> ! 50: #include <asm/bitops.h> ! 51: #include <asm/io.h> ! 52: #include <asm/dma.h> ! 53: #include <linux/errno.h> ! 54: ! 55: #include <linux/netdevice.h> ! 56: #include <linux/etherdevice.h> ! 57: #include <linux/skbuff.h> ! 58: #include <linux/malloc.h> ! 59: ! 60: /* use 0 for production, 1 for verification, 2..7 for debug */ ! 61: #ifndef NET_DEBUG ! 62: #define NET_DEBUG 2 ! 63: #endif ! 64: static unsigned int net_debug = NET_DEBUG; ! 65: ! 66: /* ! 67: Details of the i82586. ! 68: ! 69: You'll really need the databook to understand the details of this part, ! 70: but the outline is that the i82586 has two separate processing units. ! 71: ! 72: The Rx unit uses a list of frame descriptors and a list of data buffer ! 73: descriptors. We use full-sized (1518 byte) data buffers, so there is ! 74: a one-to-one pairing of frame descriptors to buffer descriptors. ! 75: ! 76: The Tx ("command") unit executes a list of commands that look like: ! 77: Status word Written by the 82586 when the command is done. ! 78: Command word Command in lower 3 bits, post-command action in upper 3 ! 79: Link word The address of the next command. ! 80: Parameters (as needed). ! 81: ! 82: Some definitions related to the Command Word are: ! 83: */ ! 84: #define CMD_EOL 0x8000 /* The last command of the list, stop. */ ! 85: #define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ ! 86: #define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ ! 87: ! 88: enum commands { ! 89: CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, ! 90: CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; ! 91: ! 92: /* Information that need to be kept for each board. */ ! 93: struct net_local { ! 94: struct enet_statistics stats; ! 95: int last_restart; ! 96: short rx_head; ! 97: short rx_tail; ! 98: short tx_head; ! 99: short tx_cmd_link; ! 100: short tx_reap; ! 101: }; ! 102: ! 103: /* ! 104: Details of the EtherExpress Implementation ! 105: The EtherExpress takes an unusual approach to host access to packet buffer ! 106: memory. The host can use either the Dataport, with independent ! 107: autoincrementing read and write pointers, or it can I/O map 32 bytes of the ! 108: memory using the "Shadow Memory Pointer" (SMB) as follows: ! 109: ioaddr Normal EtherExpress registers ! 110: ioaddr+0x4000...0x400f Buffer Memory at SMB...SMB+15 ! 111: ioaddr+0x8000...0x800f Buffer Memory at SMB+16...SMB+31 ! 112: ioaddr+0xC000...0xC007 "" SMB+16...SMB+23 (hardware flaw?) ! 113: ioaddr+0xC008...0xC00f Buffer Memory at 0x0008...0x000f ! 114: The last I/O map set is useful if you put the i82586 System Command Block ! 115: (the command mailbox) exactly at 0x0008. (There seems to be some ! 116: undocumented init structure at 0x0000-7, so I had to use the Crywnr memory ! 117: setup verbatim for those four words anyway.) ! 118: ! 119: A problem with using either one of these mechanisms is that you must run ! 120: single-threaded, or the interrupt handler must restore a changed value of ! 121: the read, write, or SMB pointers. ! 122: ! 123: Unlike the Crynwr driver, my driver mostly ignores the I/O mapped "feature" ! 124: and relies heavily on the dataport for buffer memory access. To minimize ! 125: switching, the read_pointer is dedicated to the Rx interrupt handler, and ! 126: the write_pointer is used by the send_packet() routine (it's carefully saved ! 127: and restored when it's needed by the interrupt handler). ! 128: */ ! 129: ! 130: /* Offsets from the base I/O address. */ ! 131: #define DATAPORT 0 /* Data Transfer Register. */ ! 132: #define WRITE_PTR 2 /* Write Address Pointer. */ ! 133: #define READ_PTR 4 /* Read Address Pointer. */ ! 134: #define SIGNAL_CA 6 /* Frob the 82586 Channel Attention line. */ ! 135: #define SET_IRQ 7 /* IRQ Select. */ ! 136: #define SHADOW_PTR 8 /* Shadow Memory Bank Pointer. */ ! 137: #define MEM_Ctrl 11 ! 138: #define MEM_Page_Ctrl 12 ! 139: #define Config 13 ! 140: #define EEPROM_Ctrl 14 ! 141: #define ID_PORT 15 ! 142: ! 143: #define EEXPRESS_IO_EXTENT 16 ! 144: ! 145: /* EEPROM_Ctrl bits. */ ! 146: ! 147: #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ ! 148: #define EE_CS 0x02 /* EEPROM chip select. */ ! 149: #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ ! 150: #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ ! 151: #define EE_CTRL_BITS (EE_SHIFT_CLK | EE_CS | EE_DATA_WRITE | EE_DATA_READ) ! 152: #define ASIC_RESET 0x40 ! 153: #define _586_RESET 0x80 ! 154: ! 155: /* Offsets to elements of the System Control Block structure. */ ! 156: #define SCB_STATUS 0xc008 ! 157: #define SCB_CMD 0xc00A ! 158: #define CUC_START 0x0100 ! 159: #define CUC_RESUME 0x0200 ! 160: #define CUC_SUSPEND 0x0300 ! 161: #define RX_START 0x0010 ! 162: #define RX_RESUME 0x0020 ! 163: #define RX_SUSPEND 0x0030 ! 164: #define SCB_CBL 0xc00C /* Command BLock offset. */ ! 165: #define SCB_RFA 0xc00E /* Rx Frame Area offset. */ ! 166: ! 167: /* ! 168: What follows in 'init_words[]' is the "program" that is downloaded to the ! 169: 82586 memory. It's mostly tables and command blocks, and starts at the ! 170: reset address 0xfffff6. ! 171: ! 172: Even with the additional "don't care" values, doing it this way takes less ! 173: program space than initializing the individual tables, and I feel it's much ! 174: cleaner. ! 175: ! 176: The databook is particularly useless for the first two structures; they are ! 177: completely undocumented. I had to use the Crynwr driver as an example. ! 178: ! 179: The memory setup is as follows: ! 180: */ ! 181: ! 182: #define CONFIG_CMD 0x0018 ! 183: #define SET_SA_CMD 0x0024 ! 184: #define SA_OFFSET 0x002A ! 185: #define IDLELOOP 0x30 ! 186: #define TDR_CMD 0x38 ! 187: #define TDR_TIME 0x3C ! 188: #define DUMP_CMD 0x40 ! 189: #define DIAG_CMD 0x48 ! 190: #define SET_MC_CMD 0x4E ! 191: #define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */ ! 192: ! 193: #define TX_BUF_START 0x0100 ! 194: #define NUM_TX_BUFS 4 ! 195: #define TX_BUF_SIZE 0x0680 /* packet+header+TBD+extra (1518+14+20+16) */ ! 196: #define TX_BUF_END 0x2000 ! 197: ! 198: #define RX_BUF_START 0x2000 ! 199: #define RX_BUF_SIZE (0x640) /* packet+header+RBD+extra */ ! 200: #define RX_BUF_END 0x4000 ! 201: ! 202: /* ! 203: That's it: only 86 bytes to set up the beast, including every extra ! 204: command available. The 170 byte buffer at DUMP_DATA is shared between the ! 205: Dump command (called only by the diagnostic program) and the SetMulticastList ! 206: command. ! 207: ! 208: To complete the memory setup you only have to write the station address at ! 209: SA_OFFSET and create the Tx & Rx buffer lists. ! 210: ! 211: The Tx command chain and buffer list is setup as follows: ! 212: A Tx command table, with the data buffer pointing to... ! 213: A Tx data buffer descriptor. The packet is in a single buffer, rather than ! 214: chaining together several smaller buffers. ! 215: A NoOp command, which initially points to itself, ! 216: And the packet data. ! 217: ! 218: A transmit is done by filling in the Tx command table and data buffer, ! 219: re-writing the NoOp command, and finally changing the offset of the last ! 220: command to point to the current Tx command. When the Tx command is finished, ! 221: it jumps to the NoOp, when it loops until the next Tx command changes the ! 222: "link offset" in the NoOp. This way the 82586 never has to go through the ! 223: slow restart sequence. ! 224: ! 225: The Rx buffer list is set up in the obvious ring structure. We have enough ! 226: memory (and low enough interrupt latency) that we can avoid the complicated ! 227: Rx buffer linked lists by alway associating a full-size Rx data buffer with ! 228: each Rx data frame. ! 229: ! 230: I current use four transmit buffers starting at TX_BUF_START (0x0100), and ! 231: use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers. ! 232: ! 233: */ ! 234: ! 235: static short init_words[] = { ! 236: 0x0000, /* Set bus size to 16 bits. */ ! 237: 0x0000,0x0000, /* Set control mailbox (SCB) addr. */ ! 238: 0,0, /* pad to 0x000000. */ ! 239: 0x0001, /* Status word that's cleared when init is done. */ ! 240: 0x0008,0,0, /* SCB offset, (skip, skip) */ ! 241: ! 242: 0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */ ! 243: CONFIG_CMD, /* Command list pointer, points to Configure. */ ! 244: RX_BUF_START, /* Rx block list. */ ! 245: 0,0,0,0, /* Error count: CRC, align, buffer, overrun. */ ! 246: ! 247: /* 0x0018: Configure command. Change to put MAC data with packet. */ ! 248: 0, CmdConfigure, /* Status, command. */ ! 249: SET_SA_CMD, /* Next command is Set Station Addr. */ ! 250: 0x0804, /* "4" bytes of config data, 8 byte FIFO. */ ! 251: 0x2e40, /* Magic values, including MAC data location. */ ! 252: 0, /* Unused pad word. */ ! 253: ! 254: /* 0x0024: Setup station address command. */ ! 255: 0, CmdSASetup, ! 256: SET_MC_CMD, /* Next command. */ ! 257: 0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */ ! 258: ! 259: /* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */ ! 260: 0, CmdNOp, IDLELOOP, 0 /* pad */, ! 261: ! 262: /* 0x0038: A unused Time-Domain Reflectometer command. */ ! 263: 0, CmdTDR, IDLELOOP, 0, ! 264: ! 265: /* 0x0040: An unused Dump State command. */ ! 266: 0, CmdDump, IDLELOOP, DUMP_DATA, ! 267: ! 268: /* 0x0048: An unused Diagnose command. */ ! 269: 0, CmdDiagnose, IDLELOOP, ! 270: ! 271: /* 0x004E: An empty set-multicast-list command. */ ! 272: #ifdef initial_text_tx ! 273: 0, CmdMulticastList, DUMP_DATA, 0, ! 274: #else ! 275: 0, CmdMulticastList, IDLELOOP, 0, ! 276: #endif ! 277: ! 278: /* 0x0056: A continuous transmit command, only here for testing. */ ! 279: 0, CmdTx, DUMP_DATA, DUMP_DATA+8, 0x83ff, -1, DUMP_DATA, 0, ! 280: }; ! 281: ! 282: /* Index to functions, as function prototypes. */ ! 283: ! 284: extern int express_probe(struct device *dev); /* Called from Space.c */ ! 285: ! 286: static int eexp_probe1(struct device *dev, short ioaddr); ! 287: static int eexp_open(struct device *dev); ! 288: static int eexp_send_packet(struct sk_buff *skb, struct device *dev); ! 289: static void eexp_interrupt(int irq, struct pt_regs *regs); ! 290: static void eexp_rx(struct device *dev); ! 291: static int eexp_close(struct device *dev); ! 292: static struct enet_statistics *eexp_get_stats(struct device *dev); ! 293: static void set_multicast_list(struct device *dev); ! 294: ! 295: static int read_eeprom(int ioaddr, int location); ! 296: static void hardware_send_packet(struct device *dev, void *buf, short length); ! 297: static void init_82586_mem(struct device *dev); ! 298: static void init_rx_bufs(struct device *dev); ! 299: ! 300: ! 301: /* Check for a network adaptor of this type, and return '0' iff one exists. ! 302: If dev->base_addr == 0, probe all likely locations. ! 303: If dev->base_addr == 1, always return failure. ! 304: If dev->base_addr == 2, (detachable devices only) allocate space for the ! 305: device and return success. ! 306: */ ! 307: int ! 308: express_probe(struct device *dev) ! 309: { ! 310: /* Don't probe all settable addresses, 0x[23][0-7]0, just common ones. */ ! 311: int *port, ports[] = {0x300, 0x270, 0x320, 0x340, 0}; ! 312: int base_addr = dev->base_addr; ! 313: ! 314: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 315: return eexp_probe1(dev, base_addr); ! 316: else if (base_addr > 0) ! 317: return ENXIO; /* Don't probe at all. */ ! 318: ! 319: for (port = &ports[0]; *port; port++) { ! 320: short id_addr = *port + ID_PORT; ! 321: unsigned short sum = 0; ! 322: int i; ! 323: #ifdef notdef ! 324: for (i = 16; i > 0; i--) ! 325: sum += inb(id_addr); ! 326: printk("EtherExpress ID checksum is %04x.\n", sum); ! 327: #else ! 328: for (i = 4; i > 0; i--) { ! 329: short id_val = inb(id_addr); ! 330: sum |= (id_val >> 4) << ((id_val & 3) << 2); ! 331: } ! 332: #endif ! 333: if (sum == 0xbaba ! 334: && eexp_probe1(dev, *port) == 0) ! 335: return 0; ! 336: } ! 337: ! 338: return ENODEV; ! 339: } ! 340: ! 341: int eexp_probe1(struct device *dev, short ioaddr) ! 342: { ! 343: unsigned short station_addr[3]; ! 344: int i; ! 345: ! 346: printk("%s: EtherExpress at %#x,", dev->name, ioaddr); ! 347: ! 348: /* The station address is stored !backwards! in the EEPROM, reverse ! 349: after reading. (Hmmm, a little brain-damage there at Intel, eh?) */ ! 350: station_addr[0] = read_eeprom(ioaddr, 2); ! 351: station_addr[1] = read_eeprom(ioaddr, 3); ! 352: station_addr[2] = read_eeprom(ioaddr, 4); ! 353: ! 354: /* Check the first three octets of the S.A. for the manufacturer's code. */ ! 355: if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) { ! 356: printk(" rejected (invalid address %04x%04x%04x).\n", ! 357: station_addr[2], station_addr[1], station_addr[0]); ! 358: return ENODEV; ! 359: } ! 360: ! 361: /* We've committed to using the board, and can start filling in *dev. */ ! 362: request_region(ioaddr, EEXPRESS_IO_EXTENT, "eexpress"); ! 363: dev->base_addr = ioaddr; ! 364: ! 365: for (i = 0; i < 6; i++) { ! 366: dev->dev_addr[i] = ((unsigned char*)station_addr)[5-i]; ! 367: printk(" %02x", dev->dev_addr[i]); ! 368: } ! 369: ! 370: /* There is no reason for the driver to care, but I print out the ! 371: interface to minimize bogus bug reports. */ ! 372: { ! 373: char irqmap[] = {0, 9, 3, 4, 5, 10, 11, 0}; ! 374: const char *ifmap[] = {"AUI", "BNC", "10baseT"}; ! 375: enum iftype {AUI=0, BNC=1, TP=2}; ! 376: unsigned short setupval = read_eeprom(ioaddr, 0); ! 377: ! 378: dev->irq = irqmap[setupval >> 13]; ! 379: dev->if_port = (setupval & 0x1000) == 0 ? AUI : ! 380: read_eeprom(ioaddr, 5) & 0x1 ? TP : BNC; ! 381: printk(", IRQ %d, Interface %s.\n", dev->irq, ifmap[dev->if_port]); ! 382: /* Release the IRQ line so that it can be shared if we don't use the ! 383: ethercard. */ ! 384: outb(0x00, ioaddr + SET_IRQ); ! 385: } ! 386: ! 387: /* It's now OK to leave the board in reset, pending the open(). */ ! 388: outb(ASIC_RESET, ioaddr + EEPROM_Ctrl); ! 389: ! 390: if ((dev->mem_start & 0xf) > 0) ! 391: net_debug = dev->mem_start & 7; ! 392: ! 393: if (net_debug) ! 394: printk(version); ! 395: ! 396: /* Initialize the device structure. */ ! 397: dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); ! 398: if (dev->priv == NULL) ! 399: return -ENOMEM; ! 400: memset(dev->priv, 0, sizeof(struct net_local)); ! 401: ! 402: dev->open = eexp_open; ! 403: dev->stop = eexp_close; ! 404: dev->hard_start_xmit = eexp_send_packet; ! 405: dev->get_stats = eexp_get_stats; ! 406: dev->set_multicast_list = &set_multicast_list; ! 407: ! 408: /* Fill in the fields of the device structure with ethernet-generic values. */ ! 409: ! 410: ether_setup(dev); ! 411: ! 412: dev->flags&=~IFF_MULTICAST; ! 413: ! 414: return 0; ! 415: } ! 416: ! 417: ! 418: /* Reverse IRQ map: the value to put in the SET_IRQ reg. for IRQ<index>. */ ! 419: static char irqrmap[]={0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0}; ! 420: ! 421: static int ! 422: eexp_open(struct device *dev) ! 423: { ! 424: int ioaddr = dev->base_addr; ! 425: ! 426: if (dev->irq == 0 || irqrmap[dev->irq] == 0) ! 427: return -ENXIO; ! 428: ! 429: if (irq2dev_map[dev->irq] != 0 ! 430: /* This is always true, but avoid the false IRQ. */ ! 431: || (irq2dev_map[dev->irq] = dev) == 0 ! 432: || request_irq(dev->irq, &eexp_interrupt, 0, "EExpress")) { ! 433: return -EAGAIN; ! 434: } ! 435: ! 436: /* Initialize the 82586 memory and start it. */ ! 437: init_82586_mem(dev); ! 438: ! 439: /* Enable the interrupt line. */ ! 440: outb(irqrmap[dev->irq] | 0x08, ioaddr + SET_IRQ); ! 441: ! 442: dev->tbusy = 0; ! 443: dev->interrupt = 0; ! 444: dev->start = 1; ! 445: MOD_INC_USE_COUNT; ! 446: return 0; ! 447: } ! 448: ! 449: static int ! 450: eexp_send_packet(struct sk_buff *skb, struct device *dev) ! 451: { ! 452: struct net_local *lp = (struct net_local *)dev->priv; ! 453: int ioaddr = dev->base_addr; ! 454: ! 455: if (dev->tbusy) { ! 456: /* If we get here, some higher level has decided we are broken. ! 457: There should really be a "kick me" function call instead. */ ! 458: int tickssofar = jiffies - dev->trans_start; ! 459: if (tickssofar < 5) ! 460: return 1; ! 461: if (net_debug > 1) ! 462: printk("%s: transmit timed out, %s? ", dev->name, ! 463: inw(ioaddr+SCB_STATUS) & 0x8000 ? "IRQ conflict" : ! 464: "network cable problem"); ! 465: lp->stats.tx_errors++; ! 466: /* Try to restart the adaptor. */ ! 467: if (lp->last_restart == lp->stats.tx_packets) { ! 468: if (net_debug > 1) printk("Resetting board.\n"); ! 469: /* Completely reset the adaptor. */ ! 470: init_82586_mem(dev); ! 471: } else { ! 472: /* Issue the channel attention signal and hope it "gets better". */ ! 473: if (net_debug > 1) printk("Kicking board.\n"); ! 474: outw(0xf000|CUC_START|RX_START, ioaddr + SCB_CMD); ! 475: outb(0, ioaddr + SIGNAL_CA); ! 476: lp->last_restart = lp->stats.tx_packets; ! 477: } ! 478: dev->tbusy=0; ! 479: dev->trans_start = jiffies; ! 480: } ! 481: ! 482: /* If some higher layer thinks we've missed an tx-done interrupt ! 483: we are passed NULL. Caution: dev_tint() handles the cli()/sti() ! 484: itself. */ ! 485: if (skb == NULL) { ! 486: dev_tint(dev); ! 487: return 0; ! 488: } ! 489: ! 490: /* Block a timer-based transmit from overlapping. */ ! 491: if (set_bit(0, (void*)&dev->tbusy) != 0) ! 492: printk("%s: Transmitter access conflict.\n", dev->name); ! 493: else { ! 494: short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; ! 495: unsigned char *buf = skb->data; ! 496: ! 497: /* Disable the 82586's input to the interrupt line. */ ! 498: outb(irqrmap[dev->irq], ioaddr + SET_IRQ); ! 499: hardware_send_packet(dev, buf, length); ! 500: dev->trans_start = jiffies; ! 501: /* Enable the 82586 interrupt input. */ ! 502: outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ); ! 503: } ! 504: ! 505: dev_kfree_skb (skb, FREE_WRITE); ! 506: ! 507: /* You might need to clean up and record Tx statistics here. */ ! 508: lp->stats.tx_aborted_errors++; ! 509: ! 510: return 0; ! 511: } ! 512: ! 513: /* The typical workload of the driver: ! 514: Handle the network interface interrupts. */ ! 515: static void ! 516: eexp_interrupt(int irq, struct pt_regs *regs) ! 517: { ! 518: struct device *dev = (struct device *)(irq2dev_map[irq]); ! 519: struct net_local *lp; ! 520: int ioaddr, status, boguscount = 0; ! 521: short ack_cmd; ! 522: ! 523: if (dev == NULL) { ! 524: printk ("net_interrupt(): irq %d for unknown device.\n", irq); ! 525: return; ! 526: } ! 527: dev->interrupt = 1; ! 528: ! 529: ioaddr = dev->base_addr; ! 530: lp = (struct net_local *)dev->priv; ! 531: ! 532: status = inw(ioaddr + SCB_STATUS); ! 533: ! 534: if (net_debug > 4) { ! 535: printk("%s: EExp interrupt, status %4.4x.\n", dev->name, status); ! 536: } ! 537: ! 538: /* Disable the 82586's input to the interrupt line. */ ! 539: outb(irqrmap[dev->irq], ioaddr + SET_IRQ); ! 540: ! 541: /* Reap the Tx packet buffers. */ ! 542: while (lp->tx_reap != lp->tx_head) { /* if (status & 0x8000) */ ! 543: unsigned short tx_status; ! 544: outw(lp->tx_reap, ioaddr + READ_PTR); ! 545: tx_status = inw(ioaddr); ! 546: if (tx_status == 0) { ! 547: if (net_debug > 5) printk("Couldn't reap %#x.\n", lp->tx_reap); ! 548: break; ! 549: } ! 550: if (tx_status & 0x2000) { ! 551: lp->stats.tx_packets++; ! 552: lp->stats.collisions += tx_status & 0xf; ! 553: dev->tbusy = 0; ! 554: mark_bh(NET_BH); /* Inform upper layers. */ ! 555: } else { ! 556: lp->stats.tx_errors++; ! 557: if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; ! 558: if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; ! 559: if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; ! 560: if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; ! 561: } ! 562: if (net_debug > 5) ! 563: printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); ! 564: lp->tx_reap += TX_BUF_SIZE; ! 565: if (lp->tx_reap > TX_BUF_END - TX_BUF_SIZE) ! 566: lp->tx_reap = TX_BUF_START; ! 567: if (++boguscount > 4) ! 568: break; ! 569: } ! 570: ! 571: if (status & 0x4000) { /* Packet received. */ ! 572: if (net_debug > 5) ! 573: printk("Received packet, rx_head %04x.\n", lp->rx_head); ! 574: eexp_rx(dev); ! 575: } ! 576: ! 577: /* Acknowledge the interrupt sources. */ ! 578: ack_cmd = status & 0xf000; ! 579: ! 580: if ((status & 0x0700) != 0x0200 && dev->start) { ! 581: short saved_write_ptr = inw(ioaddr + WRITE_PTR); ! 582: if (net_debug > 1) ! 583: printk("%s: Command unit stopped, status %04x, restarting.\n", ! 584: dev->name, status); ! 585: /* If this ever occurs we must re-write the idle loop, reset ! 586: the Tx list, and do a complete restart of the command unit. */ ! 587: outw(IDLELOOP, ioaddr + WRITE_PTR); ! 588: outw(0, ioaddr); ! 589: outw(CmdNOp, ioaddr); ! 590: outw(IDLELOOP, ioaddr); ! 591: outw(IDLELOOP, SCB_CBL); ! 592: lp->tx_cmd_link = IDLELOOP + 4; ! 593: lp->tx_head = lp->tx_reap = TX_BUF_START; ! 594: /* Restore the saved write pointer. */ ! 595: outw(saved_write_ptr, ioaddr + WRITE_PTR); ! 596: ack_cmd |= CUC_START; ! 597: } ! 598: ! 599: if ((status & 0x0070) != 0x0040 && dev->start) { ! 600: short saved_write_ptr = inw(ioaddr + WRITE_PTR); ! 601: /* The Rx unit is not ready, it must be hung. Restart the receiver by ! 602: initializing the rx buffers, and issuing an Rx start command. */ ! 603: lp->stats.rx_errors++; ! 604: if (net_debug > 1) { ! 605: int cur_rxbuf = RX_BUF_START; ! 606: printk("%s: Rx unit stopped status %04x rx head %04x tail %04x.\n", ! 607: dev->name, status, lp->rx_head, lp->rx_tail); ! 608: while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE) { ! 609: int i; ! 610: printk(" Rx buf at %04x:", cur_rxbuf); ! 611: outw(cur_rxbuf, ioaddr + READ_PTR); ! 612: for (i = 0; i < 0x20; i += 2) ! 613: printk(" %04x", inw(ioaddr)); ! 614: printk(".\n"); ! 615: cur_rxbuf += RX_BUF_SIZE; ! 616: } ! 617: } ! 618: init_rx_bufs(dev); ! 619: outw(RX_BUF_START, SCB_RFA); ! 620: outw(saved_write_ptr, ioaddr + WRITE_PTR); ! 621: ack_cmd |= RX_START; ! 622: } ! 623: ! 624: outw(ack_cmd, ioaddr + SCB_CMD); ! 625: outb(0, ioaddr + SIGNAL_CA); ! 626: ! 627: if (net_debug > 5) { ! 628: printk("%s: EExp exiting interrupt, status %4.4x.\n", dev->name, ! 629: inw(ioaddr + SCB_CMD)); ! 630: } ! 631: /* Enable the 82586's input to the interrupt line. */ ! 632: outb(irqrmap[dev->irq] | 0x08, ioaddr + SET_IRQ); ! 633: return; ! 634: } ! 635: ! 636: static int ! 637: eexp_close(struct device *dev) ! 638: { ! 639: int ioaddr = dev->base_addr; ! 640: ! 641: dev->tbusy = 1; ! 642: dev->start = 0; ! 643: ! 644: /* Flush the Tx and disable Rx. */ ! 645: outw(RX_SUSPEND | CUC_SUSPEND, ioaddr + SCB_CMD); ! 646: outb(0, ioaddr + SIGNAL_CA); ! 647: ! 648: /* Disable the physical interrupt line. */ ! 649: outb(0, ioaddr + SET_IRQ); ! 650: ! 651: free_irq(dev->irq); ! 652: ! 653: irq2dev_map[dev->irq] = 0; ! 654: ! 655: /* Update the statistics here. */ ! 656: ! 657: MOD_DEC_USE_COUNT; ! 658: return 0; ! 659: } ! 660: ! 661: /* Get the current statistics. This may be called with the card open or ! 662: closed. */ ! 663: static struct enet_statistics * ! 664: eexp_get_stats(struct device *dev) ! 665: { ! 666: struct net_local *lp = (struct net_local *)dev->priv; ! 667: ! 668: /* ToDo: decide if there are any useful statistics from the SCB. */ ! 669: ! 670: return &lp->stats; ! 671: } ! 672: ! 673: /* Set or clear the multicast filter for this adaptor. ! 674: */ ! 675: static void ! 676: set_multicast_list(struct device *dev) ! 677: { ! 678: /* This doesn't work yet */ ! 679: #if 0 ! 680: short ioaddr = dev->base_addr; ! 681: if (num_addrs < 0) { ! 682: /* Not written yet, this requires expanding the init_words config ! 683: cmd. */ ! 684: } else if (num_addrs > 0) { ! 685: /* Fill in the SET_MC_CMD with the number of address bytes, followed ! 686: by the list of multicast addresses to be accepted. */ ! 687: outw(SET_MC_CMD + 6, ioaddr + WRITE_PTR); ! 688: outw(num_addrs * 6, ioaddr); ! 689: outsw(ioaddr, addrs, num_addrs*3); /* 3 = addr len in words */ ! 690: /* We must trigger a whole 586 reset due to a bug. */ ! 691: } else { ! 692: /* Not written yet, this requires expanding the init_words config ! 693: cmd. */ ! 694: outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */ ! 695: } ! 696: #endif ! 697: } ! 698: ! 699: /* The horrible routine to read a word from the serial EEPROM. */ ! 700: ! 701: /* The delay between EEPROM clock transitions. */ ! 702: #define eeprom_delay() { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }} ! 703: #define EE_READ_CMD (6 << 6) ! 704: ! 705: int ! 706: read_eeprom(int ioaddr, int location) ! 707: { ! 708: int i; ! 709: unsigned short retval = 0; ! 710: short ee_addr = ioaddr + EEPROM_Ctrl; ! 711: int read_cmd = location | EE_READ_CMD; ! 712: short ctrl_val = EE_CS | _586_RESET; ! 713: ! 714: outb(ctrl_val, ee_addr); ! 715: ! 716: /* Shift the read command bits out. */ ! 717: for (i = 8; i >= 0; i--) { ! 718: short outval = (read_cmd & (1 << i)) ? ctrl_val | EE_DATA_WRITE ! 719: : ctrl_val; ! 720: outb(outval, ee_addr); ! 721: outb(outval | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ ! 722: eeprom_delay(); ! 723: outb(outval, ee_addr); /* Finish EEPROM a clock tick. */ ! 724: eeprom_delay(); ! 725: } ! 726: outb(ctrl_val, ee_addr); ! 727: ! 728: for (i = 16; i > 0; i--) { ! 729: outb(ctrl_val | EE_SHIFT_CLK, ee_addr); eeprom_delay(); ! 730: retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); ! 731: outb(ctrl_val, ee_addr); eeprom_delay(); ! 732: } ! 733: ! 734: /* Terminate the EEPROM access. */ ! 735: ctrl_val &= ~EE_CS; ! 736: outb(ctrl_val | EE_SHIFT_CLK, ee_addr); ! 737: eeprom_delay(); ! 738: outb(ctrl_val, ee_addr); ! 739: eeprom_delay(); ! 740: return retval; ! 741: } ! 742: ! 743: static void ! 744: init_82586_mem(struct device *dev) ! 745: { ! 746: struct net_local *lp = (struct net_local *)dev->priv; ! 747: short ioaddr = dev->base_addr; ! 748: ! 749: /* Enable loopback to protect the wire while starting up. ! 750: This is Superstition From Crynwr. */ ! 751: outb(inb(ioaddr + Config) | 0x02, ioaddr + Config); ! 752: ! 753: /* Hold the 586 in reset during the memory initialization. */ ! 754: outb(_586_RESET, ioaddr + EEPROM_Ctrl); ! 755: ! 756: /* Place the write pointer at 0xfff6 (address-aliased to 0xfffff6). */ ! 757: outw(0xfff6, ioaddr + WRITE_PTR); ! 758: outsw(ioaddr, init_words, sizeof(init_words)>>1); ! 759: ! 760: /* Fill in the station address. */ ! 761: outw(SA_OFFSET, ioaddr + WRITE_PTR); ! 762: outsw(ioaddr, dev->dev_addr, 3); ! 763: ! 764: /* The Tx-block list is written as needed. We just set up the values. */ ! 765: #ifdef initial_text_tx ! 766: lp->tx_cmd_link = DUMP_DATA + 4; ! 767: #else ! 768: lp->tx_cmd_link = IDLELOOP + 4; ! 769: #endif ! 770: lp->tx_head = lp->tx_reap = TX_BUF_START; ! 771: ! 772: init_rx_bufs(dev); ! 773: ! 774: /* Start the 586 by releasing the reset line. */ ! 775: outb(0x00, ioaddr + EEPROM_Ctrl); ! 776: ! 777: /* This was time consuming to track down: you need to give two channel ! 778: attention signals to reliably start up the i82586. */ ! 779: outb(0, ioaddr + SIGNAL_CA); ! 780: ! 781: { ! 782: int boguscnt = 50; ! 783: while (inw(ioaddr + SCB_STATUS) == 0) ! 784: if (--boguscnt == 0) { ! 785: printk("%s: i82586 initialization timed out with status %04x, cmd %04x.\n", ! 786: dev->name, inw(ioaddr + SCB_STATUS), inw(ioaddr + SCB_CMD)); ! 787: break; ! 788: } ! 789: /* Issue channel-attn -- the 82586 won't start without it. */ ! 790: outb(0, ioaddr + SIGNAL_CA); ! 791: } ! 792: ! 793: /* Disable loopback. */ ! 794: outb(inb(ioaddr + Config) & ~0x02, ioaddr + Config); ! 795: if (net_debug > 4) ! 796: printk("%s: Initialized 82586, status %04x.\n", dev->name, ! 797: inw(ioaddr + SCB_STATUS)); ! 798: return; ! 799: } ! 800: ! 801: /* Initialize the Rx-block list. */ ! 802: static void init_rx_bufs(struct device *dev) ! 803: { ! 804: struct net_local *lp = (struct net_local *)dev->priv; ! 805: short ioaddr = dev->base_addr; ! 806: ! 807: int cur_rxbuf = lp->rx_head = RX_BUF_START; ! 808: ! 809: /* Initialize each Rx frame + data buffer. */ ! 810: do { /* While there is room for one more. */ ! 811: outw(cur_rxbuf, ioaddr + WRITE_PTR); ! 812: outw(0x0000, ioaddr); /* Status */ ! 813: outw(0x0000, ioaddr); /* Command */ ! 814: outw(cur_rxbuf + RX_BUF_SIZE, ioaddr); /* Link */ ! 815: outw(cur_rxbuf + 22, ioaddr); /* Buffer offset */ ! 816: outw(0xFeed, ioaddr); /* Pad for dest addr. */ ! 817: outw(0xF00d, ioaddr); ! 818: outw(0xF001, ioaddr); ! 819: outw(0x0505, ioaddr); /* Pad for source addr. */ ! 820: outw(0x2424, ioaddr); ! 821: outw(0x6565, ioaddr); ! 822: outw(0xdeaf, ioaddr); /* Pad for protocol. */ ! 823: ! 824: outw(0x0000, ioaddr); /* Buffer: Actual count */ ! 825: outw(-1, ioaddr); /* Buffer: Next (none). */ ! 826: outw(cur_rxbuf + 0x20, ioaddr); /* Buffer: Address low */ ! 827: outw(0x0000, ioaddr); ! 828: /* Finally, the number of bytes in the buffer. */ ! 829: outw(0x8000 + RX_BUF_SIZE-0x20, ioaddr); ! 830: ! 831: lp->rx_tail = cur_rxbuf; ! 832: cur_rxbuf += RX_BUF_SIZE; ! 833: } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE); ! 834: ! 835: /* Terminate the list by setting the EOL bit, and wrap the pointer to make ! 836: the list a ring. */ ! 837: outw(lp->rx_tail + 2, ioaddr + WRITE_PTR); ! 838: outw(0xC000, ioaddr); /* Command, mark as last. */ ! 839: outw(lp->rx_head, ioaddr); /* Link */ ! 840: } ! 841: ! 842: static void ! 843: hardware_send_packet(struct device *dev, void *buf, short length) ! 844: { ! 845: struct net_local *lp = (struct net_local *)dev->priv; ! 846: short ioaddr = dev->base_addr; ! 847: short tx_block = lp->tx_head; ! 848: ! 849: /* Set the write pointer to the Tx block, and put out the header. */ ! 850: outw(tx_block, ioaddr + WRITE_PTR); ! 851: outw(0x0000, ioaddr); /* Tx status */ ! 852: outw(CMD_INTR|CmdTx, ioaddr); /* Tx command */ ! 853: outw(tx_block+16, ioaddr); /* Next command is a NoOp. */ ! 854: outw(tx_block+8, ioaddr); /* Data Buffer offset. */ ! 855: ! 856: /* Output the data buffer descriptor. */ ! 857: outw(length | 0x8000, ioaddr); /* Byte count parameter. */ ! 858: outw(-1, ioaddr); /* No next data buffer. */ ! 859: outw(tx_block+22, ioaddr); /* Buffer follows the NoOp command. */ ! 860: outw(0x0000, ioaddr); /* Buffer address high bits (always zero). */ ! 861: ! 862: /* Output the Loop-back NoOp command. */ ! 863: outw(0x0000, ioaddr); /* Tx status */ ! 864: outw(CmdNOp, ioaddr); /* Tx command */ ! 865: outw(tx_block+16, ioaddr); /* Next is myself. */ ! 866: ! 867: /* Output the packet using the write pointer. ! 868: Hmmm, it feels a little like a 3c501! */ ! 869: outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); ! 870: ! 871: /* Set the old command link pointing to this send packet. */ ! 872: outw(lp->tx_cmd_link, ioaddr + WRITE_PTR); ! 873: outw(tx_block, ioaddr); ! 874: lp->tx_cmd_link = tx_block + 20; ! 875: ! 876: /* Set the next free tx region. */ ! 877: lp->tx_head = tx_block + TX_BUF_SIZE; ! 878: if (lp->tx_head > TX_BUF_END - TX_BUF_SIZE) ! 879: lp->tx_head = TX_BUF_START; ! 880: ! 881: if (net_debug > 4) { ! 882: printk("%s: EExp @%x send length = %d, tx_block %3x, next %3x, " ! 883: "reap %4x status %4.4x.\n", dev->name, ioaddr, length, ! 884: tx_block, lp->tx_head, lp->tx_reap, inw(ioaddr + SCB_STATUS)); ! 885: } ! 886: ! 887: if (lp->tx_head != lp->tx_reap) ! 888: dev->tbusy = 0; ! 889: } ! 890: ! 891: static void ! 892: eexp_rx(struct device *dev) ! 893: { ! 894: struct net_local *lp = (struct net_local *)dev->priv; ! 895: short ioaddr = dev->base_addr; ! 896: short saved_write_ptr = inw(ioaddr + WRITE_PTR); ! 897: short rx_head = lp->rx_head; ! 898: short rx_tail = lp->rx_tail; ! 899: short boguscount = 10; ! 900: short frame_status; ! 901: ! 902: /* Set the read pointer to the Rx frame. */ ! 903: outw(rx_head, ioaddr + READ_PTR); ! 904: while ((frame_status = inw(ioaddr)) < 0) { /* Command complete */ ! 905: short rfd_cmd = inw(ioaddr); ! 906: short next_rx_frame = inw(ioaddr); ! 907: short data_buffer_addr = inw(ioaddr); ! 908: short pkt_len; ! 909: ! 910: /* Set the read pointer the data buffer. */ ! 911: outw(data_buffer_addr, ioaddr + READ_PTR); ! 912: pkt_len = inw(ioaddr); ! 913: ! 914: if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 ! 915: || (pkt_len & 0xC000) != 0xC000) { ! 916: printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" ! 917: "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, ! 918: frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, ! 919: pkt_len); ! 920: } else if ((frame_status & 0x2000) == 0) { ! 921: /* Frame Rxed, but with error. */ ! 922: lp->stats.rx_errors++; ! 923: if (frame_status & 0x0800) lp->stats.rx_crc_errors++; ! 924: if (frame_status & 0x0400) lp->stats.rx_frame_errors++; ! 925: if (frame_status & 0x0200) lp->stats.rx_fifo_errors++; ! 926: if (frame_status & 0x0100) lp->stats.rx_over_errors++; ! 927: if (frame_status & 0x0080) lp->stats.rx_length_errors++; ! 928: } else { ! 929: /* Malloc up new buffer. */ ! 930: struct sk_buff *skb; ! 931: ! 932: pkt_len &= 0x3fff; ! 933: skb = dev_alloc_skb(pkt_len+2); ! 934: if (skb == NULL) { ! 935: printk("%s: Memory squeeze, dropping packet.\n", dev->name); ! 936: lp->stats.rx_dropped++; ! 937: break; ! 938: } ! 939: skb->dev = dev; ! 940: skb_reserve(skb,2); ! 941: ! 942: outw(data_buffer_addr + 10, ioaddr + READ_PTR); ! 943: ! 944: insw(ioaddr, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); ! 945: ! 946: skb->protocol=eth_type_trans(skb,dev); ! 947: netif_rx(skb); ! 948: lp->stats.rx_packets++; ! 949: } ! 950: ! 951: /* Clear the status word and set End-of-List on the rx frame. */ ! 952: outw(rx_head, ioaddr + WRITE_PTR); ! 953: outw(0x0000, ioaddr); ! 954: outw(0xC000, ioaddr); ! 955: #ifndef final_version ! 956: if (next_rx_frame != rx_head + RX_BUF_SIZE ! 957: && next_rx_frame != RX_BUF_START) { ! 958: printk("%s: Rx next frame at %#x is %#x instead of %#x.\n", dev->name, ! 959: rx_head, next_rx_frame, rx_head + RX_BUF_SIZE); ! 960: next_rx_frame = rx_head + RX_BUF_SIZE; ! 961: if (next_rx_frame >= RX_BUF_END - RX_BUF_SIZE) ! 962: next_rx_frame = RX_BUF_START; ! 963: } ! 964: #endif ! 965: outw(rx_tail+2, ioaddr + WRITE_PTR); ! 966: outw(0x0000, ioaddr); /* Clear the end-of-list on the prev. RFD. */ ! 967: ! 968: #ifndef final_version ! 969: outw(rx_tail+4, ioaddr + READ_PTR); ! 970: if (inw(ioaddr) != rx_head) { ! 971: printk("%s: Rx buf link mismatch, at %04x link %04x instead of %04x.\n", ! 972: dev->name, rx_tail, (outw(rx_tail+4, ioaddr + READ_PTR),inw(ioaddr)), ! 973: rx_head); ! 974: outw(rx_head, ioaddr); ! 975: } ! 976: #endif ! 977: ! 978: rx_tail = rx_head; ! 979: rx_head = next_rx_frame; ! 980: if (--boguscount == 0) ! 981: break; ! 982: outw(rx_head, ioaddr + READ_PTR); ! 983: } ! 984: ! 985: lp->rx_head = rx_head; ! 986: lp->rx_tail = rx_tail; ! 987: ! 988: /* Restore the original write pointer. */ ! 989: outw(saved_write_ptr, ioaddr + WRITE_PTR); ! 990: } ! 991: ! 992: #ifdef MODULE ! 993: static char devicename[9] = { 0, }; ! 994: static struct device dev_eexpress = { ! 995: devicename, /* device name is inserted by linux/drivers/net/net_init.c */ ! 996: 0, 0, 0, 0, ! 997: 0, 0, ! 998: 0, 0, 0, NULL, express_probe }; ! 999: ! 1000: ! 1001: static int irq=0x300; ! 1002: static int io=0; ! 1003: ! 1004: int ! 1005: init_module(void) ! 1006: { ! 1007: if (io == 0) ! 1008: printk("eexpress: You should not use auto-probing with insmod!\n"); ! 1009: dev_eexpress.base_addr=io; ! 1010: dev_eexpress.irq=irq; ! 1011: if (register_netdev(&dev_eexpress) != 0) ! 1012: return -EIO; ! 1013: return 0; ! 1014: } ! 1015: ! 1016: void ! 1017: cleanup_module(void) ! 1018: { ! 1019: unregister_netdev(&dev_eexpress); ! 1020: kfree_s(dev_eexpress.priv,sizeof(struct net_local)); ! 1021: dev_eexpress.priv=NULL; ! 1022: ! 1023: /* If we don't do this, we can't re-insmod it later. */ ! 1024: release_region(dev_eexpress.base_addr, EEXPRESS_IO_EXTENT); ! 1025: } ! 1026: #endif /* MODULE */ ! 1027: /* ! 1028: * Local variables: ! 1029: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c eexpress.c" ! 1030: * version-control: t ! 1031: * kept-new-versions: 5 ! 1032: * tab-width: 4 ! 1033: * End: ! 1034: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.