|
|
1.1 ! root 1: /* 3c507.c: An EtherLink16 device driver for Linux. */ ! 2: /* ! 3: Written 1993,1994 by Donald Becker. ! 4: ! 5: Copyright 1993 United States Government as represented by the ! 6: Director, National Security Agency. ! 7: ! 8: This software may be used and distributed according to the terms ! 9: of the GNU Public License, incorporated herein by reference. ! 10: ! 11: The author may be reached as [email protected], or C/O ! 12: Center of Excellence in Space Data and Information Sciences ! 13: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! 14: ! 15: Thanks go to [email protected] ( Patrick Jennings) ! 16: and [email protected] (Rick Sladkey) for testing and bugfixes. ! 17: Mark Salazar <[email protected]> made the changes for cards with ! 18: only 16K packet buffers. ! 19: ! 20: Things remaining to do: ! 21: Verify that the tx and rx buffers don't have fencepost errors. ! 22: Move the theory of operation and memory map documentation. ! 23: The statistics need to be updated correctly. ! 24: */ ! 25: ! 26: static const char *version = ! 27: "3c507.c:v1.10 9/23/94 Donald Becker ([email protected])\n"; ! 28: ! 29: ! 30: #include <linux/module.h> ! 31: ! 32: /* ! 33: Sources: ! 34: This driver wouldn't have been written with the availability of the ! 35: Crynwr driver source code. It provided a known-working implementation ! 36: that filled in the gaping holes of the Intel documentation. Three cheers ! 37: for Russ Nelson. ! 38: ! 39: Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough ! 40: info that the casual reader might think that it documents the i82586 :-<. ! 41: */ ! 42: ! 43: #include <linux/kernel.h> ! 44: #include <linux/sched.h> ! 45: #include <linux/types.h> ! 46: #include <linux/fcntl.h> ! 47: #include <linux/interrupt.h> ! 48: #include <linux/ptrace.h> ! 49: #include <linux/ioport.h> ! 50: #include <linux/in.h> ! 51: #include <linux/string.h> ! 52: #include <asm/system.h> ! 53: #include <asm/bitops.h> ! 54: #include <asm/io.h> ! 55: #include <asm/dma.h> ! 56: #include <linux/errno.h> ! 57: ! 58: #include <linux/netdevice.h> ! 59: #include <linux/etherdevice.h> ! 60: #include <linux/skbuff.h> ! 61: #include <linux/malloc.h> ! 62: ! 63: ! 64: /* use 0 for production, 1 for verification, 2..7 for debug */ ! 65: #ifndef NET_DEBUG ! 66: #define NET_DEBUG 1 ! 67: #endif ! 68: static unsigned int net_debug = NET_DEBUG; ! 69: ! 70: /* A zero-terminated list of common I/O addresses to be probed. */ ! 71: static unsigned int netcard_portlist[] = ! 72: { 0x300, 0x320, 0x340, 0x280, 0}; ! 73: ! 74: /* ! 75: Details of the i82586. ! 76: ! 77: You'll really need the databook to understand the details of this part, ! 78: but the outline is that the i82586 has two separate processing units. ! 79: Both are started from a list of three configuration tables, of which only ! 80: the last, the System Control Block (SCB), is used after reset-time. The SCB ! 81: has the following fields: ! 82: Status word ! 83: Command word ! 84: Tx/Command block addr. ! 85: Rx block addr. ! 86: The command word accepts the following controls for the Tx and Rx units: ! 87: */ ! 88: ! 89: #define CUC_START 0x0100 ! 90: #define CUC_RESUME 0x0200 ! 91: #define CUC_SUSPEND 0x0300 ! 92: #define RX_START 0x0010 ! 93: #define RX_RESUME 0x0020 ! 94: #define RX_SUSPEND 0x0030 ! 95: ! 96: /* The Rx unit uses a list of frame descriptors and a list of data buffer ! 97: descriptors. We use full-sized (1518 byte) data buffers, so there is ! 98: a one-to-one pairing of frame descriptors to buffer descriptors. ! 99: ! 100: The Tx ("command") unit executes a list of commands that look like: ! 101: Status word Written by the 82586 when the command is done. ! 102: Command word Command in lower 3 bits, post-command action in upper 3 ! 103: Link word The address of the next command. ! 104: Parameters (as needed). ! 105: ! 106: Some definitions related to the Command Word are: ! 107: */ ! 108: #define CMD_EOL 0x8000 /* The last command of the list, stop. */ ! 109: #define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ ! 110: #define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ ! 111: ! 112: enum commands { ! 113: CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, ! 114: CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; ! 115: ! 116: /* Information that need to be kept for each board. */ ! 117: struct net_local { ! 118: struct enet_statistics stats; ! 119: int last_restart; ! 120: ushort rx_head; ! 121: ushort rx_tail; ! 122: ushort tx_head; ! 123: ushort tx_cmd_link; ! 124: ushort tx_reap; ! 125: }; ! 126: ! 127: /* ! 128: Details of the EtherLink16 Implementation ! 129: The 3c507 is a generic shared-memory i82586 implementation. ! 130: The host can map 16K, 32K, 48K, or 64K of the 64K memory into ! 131: 0x0[CD][08]0000, or all 64K into 0xF[02468]0000. ! 132: */ ! 133: ! 134: /* Offsets from the base I/O address. */ ! 135: #define SA_DATA 0 /* Station address data, or 3Com signature. */ ! 136: #define MISC_CTRL 6 /* Switch the SA_DATA banks, and bus config bits. */ ! 137: #define RESET_IRQ 10 /* Reset the latched IRQ line. */ ! 138: #define SIGNAL_CA 11 /* Frob the 82586 Channel Attention line. */ ! 139: #define ROM_CONFIG 13 ! 140: #define MEM_CONFIG 14 ! 141: #define IRQ_CONFIG 15 ! 142: #define EL16_IO_EXTENT 16 ! 143: ! 144: /* The ID port is used at boot-time to locate the ethercard. */ ! 145: #define ID_PORT 0x100 ! 146: ! 147: /* Offsets to registers in the mailbox (SCB). */ ! 148: #define iSCB_STATUS 0x8 ! 149: #define iSCB_CMD 0xA ! 150: #define iSCB_CBL 0xC /* Command BLock offset. */ ! 151: #define iSCB_RFA 0xE /* Rx Frame Area offset. */ ! 152: ! 153: /* Since the 3c507 maps the shared memory window so that the last byte is ! 154: at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or ! 155: 48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively. ! 156: We can account for this be setting the 'SBC Base' entry in the ISCP table ! 157: below for all the 16 bit offset addresses, and also adding the 'SCB Base' ! 158: value to all 24 bit physical addresses (in the SCP table and the TX and RX ! 159: Buffer Descriptors). ! 160: -Mark ! 161: */ ! 162: #define SCB_BASE ((unsigned)64*1024 - (dev->mem_end - dev->mem_start)) ! 163: ! 164: /* ! 165: What follows in 'init_words[]' is the "program" that is downloaded to the ! 166: 82586 memory. It's mostly tables and command blocks, and starts at the ! 167: reset address 0xfffff6. This is designed to be similar to the EtherExpress, ! 168: thus the unusual location of the SCB at 0x0008. ! 169: ! 170: Even with the additional "don't care" values, doing it this way takes less ! 171: program space than initializing the individual tables, and I feel it's much ! 172: cleaner. ! 173: ! 174: The databook is particularly useless for the first two structures, I had ! 175: to use the Crynwr driver as an example. ! 176: ! 177: The memory setup is as follows: ! 178: */ ! 179: ! 180: #define CONFIG_CMD 0x0018 ! 181: #define SET_SA_CMD 0x0024 ! 182: #define SA_OFFSET 0x002A ! 183: #define IDLELOOP 0x30 ! 184: #define TDR_CMD 0x38 ! 185: #define TDR_TIME 0x3C ! 186: #define DUMP_CMD 0x40 ! 187: #define DIAG_CMD 0x48 ! 188: #define SET_MC_CMD 0x4E ! 189: #define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */ ! 190: ! 191: #define TX_BUF_START 0x0100 ! 192: #define NUM_TX_BUFS 4 ! 193: #define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */ ! 194: ! 195: #define RX_BUF_START 0x2000 ! 196: #define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */ ! 197: #define RX_BUF_END (dev->mem_end - dev->mem_start) ! 198: ! 199: /* ! 200: That's it: only 86 bytes to set up the beast, including every extra ! 201: command available. The 170 byte buffer at DUMP_DATA is shared between the ! 202: Dump command (called only by the diagnostic program) and the SetMulticastList ! 203: command. ! 204: ! 205: To complete the memory setup you only have to write the station address at ! 206: SA_OFFSET and create the Tx & Rx buffer lists. ! 207: ! 208: The Tx command chain and buffer list is setup as follows: ! 209: A Tx command table, with the data buffer pointing to... ! 210: A Tx data buffer descriptor. The packet is in a single buffer, rather than ! 211: chaining together several smaller buffers. ! 212: A NoOp command, which initially points to itself, ! 213: And the packet data. ! 214: ! 215: A transmit is done by filling in the Tx command table and data buffer, ! 216: re-writing the NoOp command, and finally changing the offset of the last ! 217: command to point to the current Tx command. When the Tx command is finished, ! 218: it jumps to the NoOp, when it loops until the next Tx command changes the ! 219: "link offset" in the NoOp. This way the 82586 never has to go through the ! 220: slow restart sequence. ! 221: ! 222: The Rx buffer list is set up in the obvious ring structure. We have enough ! 223: memory (and low enough interrupt latency) that we can avoid the complicated ! 224: Rx buffer linked lists by alway associating a full-size Rx data buffer with ! 225: each Rx data frame. ! 226: ! 227: I current use four transmit buffers starting at TX_BUF_START (0x0100), and ! 228: use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers. ! 229: ! 230: */ ! 231: ! 232: unsigned short init_words[] = { ! 233: /* System Configuration Pointer (SCP). */ ! 234: 0x0000, /* Set bus size to 16 bits. */ ! 235: 0,0, /* pad words. */ ! 236: 0x0000,0x0000, /* ISCP phys addr, set in init_82586_mem(). */ ! 237: ! 238: /* Intermediate System Configuration Pointer (ISCP). */ ! 239: 0x0001, /* Status word that's cleared when init is done. */ ! 240: 0x0008,0,0, /* SCB offset, (skip, skip) */ ! 241: ! 242: /* System Control Block (SCB). */ ! 243: 0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */ ! 244: CONFIG_CMD, /* Command list pointer, points to Configure. */ ! 245: RX_BUF_START, /* Rx block list. */ ! 246: 0,0,0,0, /* Error count: CRC, align, buffer, overrun. */ ! 247: ! 248: /* 0x0018: Configure command. Change to put MAC data with packet. */ ! 249: 0, CmdConfigure, /* Status, command. */ ! 250: SET_SA_CMD, /* Next command is Set Station Addr. */ ! 251: 0x0804, /* "4" bytes of config data, 8 byte FIFO. */ ! 252: 0x2e40, /* Magic values, including MAC data location. */ ! 253: 0, /* Unused pad word. */ ! 254: ! 255: /* 0x0024: Setup station address command. */ ! 256: 0, CmdSASetup, ! 257: SET_MC_CMD, /* Next command. */ ! 258: 0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */ ! 259: ! 260: /* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */ ! 261: 0, CmdNOp, IDLELOOP, 0 /* pad */, ! 262: ! 263: /* 0x0038: A unused Time-Domain Reflectometer command. */ ! 264: 0, CmdTDR, IDLELOOP, 0, ! 265: ! 266: /* 0x0040: An unused Dump State command. */ ! 267: 0, CmdDump, IDLELOOP, DUMP_DATA, ! 268: ! 269: /* 0x0048: An unused Diagnose command. */ ! 270: 0, CmdDiagnose, IDLELOOP, ! 271: ! 272: /* 0x004E: An empty set-multicast-list command. */ ! 273: 0, CmdMulticastList, IDLELOOP, 0, ! 274: }; ! 275: ! 276: /* Index to functions, as function prototypes. */ ! 277: ! 278: extern int el16_probe(struct device *dev); /* Called from Space.c */ ! 279: ! 280: static int el16_probe1(struct device *dev, int ioaddr); ! 281: static int el16_open(struct device *dev); ! 282: static int el16_send_packet(struct sk_buff *skb, struct device *dev); ! 283: static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs); ! 284: static void el16_rx(struct device *dev); ! 285: static int el16_close(struct device *dev); ! 286: static struct enet_statistics *el16_get_stats(struct device *dev); ! 287: ! 288: static void hardware_send_packet(struct device *dev, void *buf, short length); ! 289: void init_82586_mem(struct device *dev); ! 290: ! 291: ! 292: #ifdef HAVE_DEVLIST ! 293: struct netdev_entry netcard_drv = ! 294: {"3c507", el16_probe1, EL16_IO_EXTENT, netcard_portlist}; ! 295: #endif ! 296: ! 297: /* Check for a network adaptor of this type, and return '0' iff one exists. ! 298: If dev->base_addr == 0, probe all likely locations. ! 299: If dev->base_addr == 1, always return failure. ! 300: If dev->base_addr == 2, (detachable devices only) allocate space for the ! 301: device and return success. ! 302: */ ! 303: int ! 304: el16_probe(struct device *dev) ! 305: { ! 306: int base_addr = dev ? dev->base_addr : 0; ! 307: int i; ! 308: ! 309: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 310: return el16_probe1(dev, base_addr); ! 311: else if (base_addr != 0) ! 312: return ENXIO; /* Don't probe at all. */ ! 313: ! 314: for (i = 0; netcard_portlist[i]; i++) { ! 315: int ioaddr = netcard_portlist[i]; ! 316: if (check_region(ioaddr, EL16_IO_EXTENT)) ! 317: continue; ! 318: if (el16_probe1(dev, ioaddr) == 0) ! 319: return 0; ! 320: } ! 321: ! 322: return ENODEV; ! 323: } ! 324: ! 325: int el16_probe1(struct device *dev, int ioaddr) ! 326: { ! 327: static unsigned char init_ID_done = 0, version_printed = 0; ! 328: int i, irq, irqval; ! 329: ! 330: if (init_ID_done == 0) { ! 331: ushort lrs_state = 0xff; ! 332: /* Send the ID sequence to the ID_PORT to enable the board(s). */ ! 333: outb(0x00, ID_PORT); ! 334: for(i = 0; i < 255; i++) { ! 335: outb(lrs_state, ID_PORT); ! 336: lrs_state <<= 1; ! 337: if (lrs_state & 0x100) ! 338: lrs_state ^= 0xe7; ! 339: } ! 340: outb(0x00, ID_PORT); ! 341: init_ID_done = 1; ! 342: } ! 343: ! 344: if (inb(ioaddr) == '*' && inb(ioaddr+1) == '3' ! 345: && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O') ! 346: ; ! 347: else ! 348: return ENODEV; ! 349: ! 350: /* Allocate a new 'dev' if needed. */ ! 351: if (dev == NULL) ! 352: dev = init_etherdev(0, sizeof(struct net_local)); ! 353: ! 354: if (net_debug && version_printed++ == 0) ! 355: printk(version); ! 356: ! 357: printk("%s: 3c507 at %#x,", dev->name, ioaddr); ! 358: ! 359: /* We should make a few more checks here, like the first three octets of ! 360: the S.A. for the manufacturer's code. */ ! 361: ! 362: irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; ! 363: ! 364: irqval = request_irq(irq, &el16_interrupt, 0, "3c507", NULL); ! 365: if (irqval) { ! 366: printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); ! 367: return EAGAIN; ! 368: } ! 369: ! 370: /* We've committed to using the board, and can start filling in *dev. */ ! 371: request_region(ioaddr, EL16_IO_EXTENT, "3c507"); ! 372: dev->base_addr = ioaddr; ! 373: ! 374: outb(0x01, ioaddr + MISC_CTRL); ! 375: for (i = 0; i < 6; i++) { ! 376: dev->dev_addr[i] = inb(ioaddr + i); ! 377: printk(" %02x", dev->dev_addr[i]); ! 378: } ! 379: ! 380: if ((dev->mem_start & 0xf) > 0) ! 381: net_debug = dev->mem_start & 7; ! 382: ! 383: #ifdef MEM_BASE ! 384: dev->mem_start = MEM_BASE; ! 385: dev->mem_end = dev->mem_start + 0x10000; ! 386: #else ! 387: { ! 388: int base; ! 389: int size; ! 390: char mem_config = inb(ioaddr + MEM_CONFIG); ! 391: if (mem_config & 0x20) { ! 392: size = 64*1024; ! 393: base = 0xf00000 + (mem_config & 0x08 ? 0x080000 ! 394: : ((mem_config & 3) << 17)); ! 395: } else { ! 396: size = ((mem_config & 3) + 1) << 14; ! 397: base = 0x0c0000 + ( (mem_config & 0x18) << 12); ! 398: } ! 399: dev->mem_start = base; ! 400: dev->mem_end = base + size; ! 401: } ! 402: #endif ! 403: ! 404: dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0; ! 405: dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; ! 406: ! 407: printk(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq, ! 408: dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1); ! 409: ! 410: if (net_debug) ! 411: printk(version); ! 412: ! 413: /* Initialize the device structure. */ ! 414: dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); ! 415: if (dev->priv == NULL) ! 416: return -ENOMEM; ! 417: memset(dev->priv, 0, sizeof(struct net_local)); ! 418: ! 419: dev->open = el16_open; ! 420: dev->stop = el16_close; ! 421: dev->hard_start_xmit = el16_send_packet; ! 422: dev->get_stats = el16_get_stats; ! 423: ! 424: ether_setup(dev); /* Generic ethernet behaviour */ ! 425: ! 426: dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ ! 427: ! 428: return 0; ! 429: } ! 430: ! 431: ! 432: ! 433: static int ! 434: el16_open(struct device *dev) ! 435: { ! 436: irq2dev_map[dev->irq] = dev; ! 437: ! 438: /* Initialize the 82586 memory and start it. */ ! 439: init_82586_mem(dev); ! 440: ! 441: dev->tbusy = 0; ! 442: dev->interrupt = 0; ! 443: dev->start = 1; ! 444: ! 445: MOD_INC_USE_COUNT; ! 446: ! 447: return 0; ! 448: } ! 449: ! 450: static int ! 451: el16_send_packet(struct sk_buff *skb, struct device *dev) ! 452: { ! 453: struct net_local *lp = (struct net_local *)dev->priv; ! 454: int ioaddr = dev->base_addr; ! 455: short *shmem = (short*)dev->mem_start; ! 456: ! 457: if (dev->tbusy) { ! 458: /* If we get here, some higher level has decided we are broken. ! 459: There should really be a "kick me" function call instead. */ ! 460: int tickssofar = jiffies - dev->trans_start; ! 461: if (tickssofar < 5) ! 462: return 1; ! 463: if (net_debug > 1) ! 464: printk("%s: transmit timed out, %s? ", dev->name, ! 465: shmem[iSCB_STATUS>>1] & 0x8000 ? "IRQ conflict" : ! 466: "network cable problem"); ! 467: /* Try to restart the adaptor. */ ! 468: if (lp->last_restart == lp->stats.tx_packets) { ! 469: if (net_debug > 1) printk("Resetting board.\n"); ! 470: /* Completely reset the adaptor. */ ! 471: init_82586_mem(dev); ! 472: } else { ! 473: /* Issue the channel attention signal and hope it "gets better". */ ! 474: if (net_debug > 1) printk("Kicking board.\n"); ! 475: shmem[iSCB_CMD>>1] = 0xf000|CUC_START|RX_START; ! 476: outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ ! 477: lp->last_restart = lp->stats.tx_packets; ! 478: } ! 479: dev->tbusy=0; ! 480: dev->trans_start = jiffies; ! 481: } ! 482: ! 483: /* If some higher layer thinks we've missed an tx-done interrupt ! 484: we are passed NULL. Caution: dev_tint() handles the cli()/sti() ! 485: itself. */ ! 486: if (skb == NULL) { ! 487: dev_tint(dev); ! 488: return 0; ! 489: } ! 490: ! 491: /* Block a timer-based transmit from overlapping. */ ! 492: if (set_bit(0, (void*)&dev->tbusy) != 0) ! 493: printk("%s: Transmitter access conflict.\n", dev->name); ! 494: else { ! 495: short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; ! 496: unsigned char *buf = skb->data; ! 497: ! 498: /* Disable the 82586's input to the interrupt line. */ ! 499: outb(0x80, ioaddr + MISC_CTRL); ! 500: hardware_send_packet(dev, buf, length); ! 501: dev->trans_start = jiffies; ! 502: /* Enable the 82586 interrupt input. */ ! 503: outb(0x84, ioaddr + MISC_CTRL); ! 504: } ! 505: ! 506: dev_kfree_skb (skb, FREE_WRITE); ! 507: ! 508: /* You might need to clean up and record Tx statistics here. */ ! 509: ! 510: return 0; ! 511: } ! 512: ! 513: /* The typical workload of the driver: ! 514: Handle the network interface interrupts. */ ! 515: static void ! 516: el16_interrupt(int irq, void *dev_id, 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: ushort ack_cmd = 0; ! 522: ushort *shmem; ! 523: ! 524: if (dev == NULL) { ! 525: printk ("net_interrupt(): irq %d for unknown device.\n", irq); ! 526: return; ! 527: } ! 528: dev->interrupt = 1; ! 529: ! 530: ioaddr = dev->base_addr; ! 531: lp = (struct net_local *)dev->priv; ! 532: shmem = ((ushort*)dev->mem_start); ! 533: ! 534: status = shmem[iSCB_STATUS>>1]; ! 535: ! 536: if (net_debug > 4) { ! 537: printk("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status); ! 538: } ! 539: ! 540: /* Disable the 82586's input to the interrupt line. */ ! 541: outb(0x80, ioaddr + MISC_CTRL); ! 542: ! 543: /* Reap the Tx packet buffers. */ ! 544: while (lp->tx_reap != lp->tx_head) { ! 545: unsigned short tx_status = shmem[lp->tx_reap>>1]; ! 546: ! 547: if (tx_status == 0) { ! 548: if (net_debug > 5) printk("Couldn't reap %#x.\n", lp->tx_reap); ! 549: break; ! 550: } ! 551: if (tx_status & 0x2000) { ! 552: lp->stats.tx_packets++; ! 553: lp->stats.collisions += tx_status & 0xf; ! 554: dev->tbusy = 0; ! 555: mark_bh(NET_BH); /* Inform upper layers. */ ! 556: } else { ! 557: lp->stats.tx_errors++; ! 558: if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; ! 559: if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; ! 560: if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; ! 561: if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; ! 562: } ! 563: if (net_debug > 5) ! 564: printk("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); ! 565: lp->tx_reap += TX_BUF_SIZE; ! 566: if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE) ! 567: lp->tx_reap = TX_BUF_START; ! 568: if (++boguscount > 4) ! 569: break; ! 570: } ! 571: ! 572: if (status & 0x4000) { /* Packet received. */ ! 573: if (net_debug > 5) ! 574: printk("Received packet, rx_head %04x.\n", lp->rx_head); ! 575: el16_rx(dev); ! 576: } ! 577: ! 578: /* Acknowledge the interrupt sources. */ ! 579: ack_cmd = status & 0xf000; ! 580: ! 581: if ((status & 0x0700) != 0x0200 && dev->start) { ! 582: if (net_debug) ! 583: printk("%s: Command unit stopped, status %04x, restarting.\n", ! 584: dev->name, status); ! 585: /* If this ever occurs we should really re-write the idle loop, reset ! 586: the Tx list, and do a complete restart of the command unit. ! 587: For now we rely on the Tx timeout if the resume doesn't work. */ ! 588: ack_cmd |= CUC_RESUME; ! 589: } ! 590: ! 591: if ((status & 0x0070) != 0x0040 && dev->start) { ! 592: static void init_rx_bufs(struct device *); ! 593: /* The Rx unit is not ready, it must be hung. Restart the receiver by ! 594: initializing the rx buffers, and issuing an Rx start command. */ ! 595: if (net_debug) ! 596: printk("%s: Rx unit stopped, status %04x, restarting.\n", ! 597: dev->name, status); ! 598: init_rx_bufs(dev); ! 599: shmem[iSCB_RFA >> 1] = RX_BUF_START; ! 600: ack_cmd |= RX_START; ! 601: } ! 602: ! 603: shmem[iSCB_CMD>>1] = ack_cmd; ! 604: outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ ! 605: ! 606: /* Clear the latched interrupt. */ ! 607: outb(0, ioaddr + RESET_IRQ); ! 608: ! 609: /* Enable the 82586's interrupt input. */ ! 610: outb(0x84, ioaddr + MISC_CTRL); ! 611: ! 612: return; ! 613: } ! 614: ! 615: static int ! 616: el16_close(struct device *dev) ! 617: { ! 618: int ioaddr = dev->base_addr; ! 619: ushort *shmem = (short*)dev->mem_start; ! 620: ! 621: dev->tbusy = 1; ! 622: dev->start = 0; ! 623: ! 624: /* Flush the Tx and disable Rx. */ ! 625: shmem[iSCB_CMD >> 1] = RX_SUSPEND | CUC_SUSPEND; ! 626: outb(0, ioaddr + SIGNAL_CA); ! 627: ! 628: /* Disable the 82586's input to the interrupt line. */ ! 629: outb(0x80, ioaddr + MISC_CTRL); ! 630: ! 631: /* We always physically use the IRQ line, so we don't do free_irq(). ! 632: We do remove ourselves from the map. */ ! 633: ! 634: irq2dev_map[dev->irq] = 0; ! 635: ! 636: /* Update the statistics here. */ ! 637: ! 638: MOD_DEC_USE_COUNT; ! 639: ! 640: return 0; ! 641: } ! 642: ! 643: /* Get the current statistics. This may be called with the card open or ! 644: closed. */ ! 645: static struct enet_statistics * ! 646: el16_get_stats(struct device *dev) ! 647: { ! 648: struct net_local *lp = (struct net_local *)dev->priv; ! 649: ! 650: /* ToDo: decide if there are any useful statistics from the SCB. */ ! 651: ! 652: return &lp->stats; ! 653: } ! 654: ! 655: /* Initialize the Rx-block list. */ ! 656: static void ! 657: init_rx_bufs(struct device *dev) ! 658: { ! 659: struct net_local *lp = (struct net_local *)dev->priv; ! 660: unsigned short *write_ptr; ! 661: unsigned short SCB_base = SCB_BASE; ! 662: ! 663: int cur_rxbuf = lp->rx_head = RX_BUF_START; ! 664: ! 665: /* Initialize each Rx frame + data buffer. */ ! 666: do { /* While there is room for one more. */ ! 667: ! 668: write_ptr = (unsigned short *)(dev->mem_start + cur_rxbuf); ! 669: ! 670: *write_ptr++ = 0x0000; /* Status */ ! 671: *write_ptr++ = 0x0000; /* Command */ ! 672: *write_ptr++ = cur_rxbuf + RX_BUF_SIZE; /* Link */ ! 673: *write_ptr++ = cur_rxbuf + 22; /* Buffer offset */ ! 674: *write_ptr++ = 0x0000; /* Pad for dest addr. */ ! 675: *write_ptr++ = 0x0000; ! 676: *write_ptr++ = 0x0000; ! 677: *write_ptr++ = 0x0000; /* Pad for source addr. */ ! 678: *write_ptr++ = 0x0000; ! 679: *write_ptr++ = 0x0000; ! 680: *write_ptr++ = 0x0000; /* Pad for protocol. */ ! 681: ! 682: *write_ptr++ = 0x0000; /* Buffer: Actual count */ ! 683: *write_ptr++ = -1; /* Buffer: Next (none). */ ! 684: *write_ptr++ = cur_rxbuf + 0x20 + SCB_base; /* Buffer: Address low */ ! 685: *write_ptr++ = 0x0000; ! 686: /* Finally, the number of bytes in the buffer. */ ! 687: *write_ptr++ = 0x8000 + RX_BUF_SIZE-0x20; ! 688: ! 689: lp->rx_tail = cur_rxbuf; ! 690: cur_rxbuf += RX_BUF_SIZE; ! 691: } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE); ! 692: ! 693: /* Terminate the list by setting the EOL bit, and wrap the pointer to make ! 694: the list a ring. */ ! 695: write_ptr = (unsigned short *) ! 696: (dev->mem_start + lp->rx_tail + 2); ! 697: *write_ptr++ = 0xC000; /* Command, mark as last. */ ! 698: *write_ptr++ = lp->rx_head; /* Link */ ! 699: ! 700: } ! 701: ! 702: void ! 703: init_82586_mem(struct device *dev) ! 704: { ! 705: struct net_local *lp = (struct net_local *)dev->priv; ! 706: short ioaddr = dev->base_addr; ! 707: ushort *shmem = (short*)dev->mem_start; ! 708: ! 709: /* Enable loopback to protect the wire while starting up, ! 710: and hold the 586 in reset during the memory initialization. */ ! 711: outb(0x20, ioaddr + MISC_CTRL); ! 712: ! 713: /* Fix the ISCP address and base. */ ! 714: init_words[3] = SCB_BASE; ! 715: init_words[7] = SCB_BASE; ! 716: ! 717: /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */ ! 718: memcpy((void*)dev->mem_end-10, init_words, 10); ! 719: ! 720: /* Write the words at 0x0000. */ ! 721: memcpy((char*)dev->mem_start, init_words + 5, sizeof(init_words) - 10); ! 722: ! 723: /* Fill in the station address. */ ! 724: memcpy((char*)dev->mem_start+SA_OFFSET, dev->dev_addr, ! 725: sizeof(dev->dev_addr)); ! 726: ! 727: /* The Tx-block list is written as needed. We just set up the values. */ ! 728: lp->tx_cmd_link = IDLELOOP + 4; ! 729: lp->tx_head = lp->tx_reap = TX_BUF_START; ! 730: ! 731: init_rx_bufs(dev); ! 732: ! 733: /* Start the 586 by releasing the reset line, but leave loopback. */ ! 734: outb(0xA0, ioaddr + MISC_CTRL); ! 735: ! 736: /* This was time consuming to track down: you need to give two channel ! 737: attention signals to reliably start up the i82586. */ ! 738: outb(0, ioaddr + SIGNAL_CA); ! 739: ! 740: { ! 741: int boguscnt = 50; ! 742: while (shmem[iSCB_STATUS>>1] == 0) ! 743: if (--boguscnt == 0) { ! 744: printk("%s: i82586 initialization timed out with status %04x," ! 745: "cmd %04x.\n", dev->name, ! 746: shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]); ! 747: break; ! 748: } ! 749: /* Issue channel-attn -- the 82586 won't start. */ ! 750: outb(0, ioaddr + SIGNAL_CA); ! 751: } ! 752: ! 753: /* Disable loopback and enable interrupts. */ ! 754: outb(0x84, ioaddr + MISC_CTRL); ! 755: if (net_debug > 4) ! 756: printk("%s: Initialized 82586, status %04x.\n", dev->name, ! 757: shmem[iSCB_STATUS>>1]); ! 758: return; ! 759: } ! 760: ! 761: static void ! 762: hardware_send_packet(struct device *dev, void *buf, short length) ! 763: { ! 764: struct net_local *lp = (struct net_local *)dev->priv; ! 765: short ioaddr = dev->base_addr; ! 766: ushort tx_block = lp->tx_head; ! 767: ushort *write_ptr = (ushort *)(dev->mem_start + tx_block); ! 768: ! 769: /* Set the write pointer to the Tx block, and put out the header. */ ! 770: *write_ptr++ = 0x0000; /* Tx status */ ! 771: *write_ptr++ = CMD_INTR|CmdTx; /* Tx command */ ! 772: *write_ptr++ = tx_block+16; /* Next command is a NoOp. */ ! 773: *write_ptr++ = tx_block+8; /* Data Buffer offset. */ ! 774: ! 775: /* Output the data buffer descriptor. */ ! 776: *write_ptr++ = length | 0x8000; /* Byte count parameter. */ ! 777: *write_ptr++ = -1; /* No next data buffer. */ ! 778: *write_ptr++ = tx_block+22+SCB_BASE;/* Buffer follows the NoOp command. */ ! 779: *write_ptr++ = 0x0000; /* Buffer address high bits (always zero). */ ! 780: ! 781: /* Output the Loop-back NoOp command. */ ! 782: *write_ptr++ = 0x0000; /* Tx status */ ! 783: *write_ptr++ = CmdNOp; /* Tx command */ ! 784: *write_ptr++ = tx_block+16; /* Next is myself. */ ! 785: ! 786: /* Output the packet at the write pointer. */ ! 787: memcpy(write_ptr, buf, length); ! 788: ! 789: /* Set the old command link pointing to this send packet. */ ! 790: *(ushort*)(dev->mem_start + lp->tx_cmd_link) = tx_block; ! 791: lp->tx_cmd_link = tx_block + 20; ! 792: ! 793: /* Set the next free tx region. */ ! 794: lp->tx_head = tx_block + TX_BUF_SIZE; ! 795: if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE) ! 796: lp->tx_head = TX_BUF_START; ! 797: ! 798: if (net_debug > 4) { ! 799: printk("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n", ! 800: dev->name, ioaddr, length, tx_block, lp->tx_head); ! 801: } ! 802: ! 803: if (lp->tx_head != lp->tx_reap) ! 804: dev->tbusy = 0; ! 805: } ! 806: ! 807: static void ! 808: el16_rx(struct device *dev) ! 809: { ! 810: struct net_local *lp = (struct net_local *)dev->priv; ! 811: short *shmem = (short*)dev->mem_start; ! 812: ushort rx_head = lp->rx_head; ! 813: ushort rx_tail = lp->rx_tail; ! 814: ushort boguscount = 10; ! 815: short frame_status; ! 816: ! 817: while ((frame_status = shmem[rx_head>>1]) < 0) { /* Command complete */ ! 818: ushort *read_frame = (short *)(dev->mem_start + rx_head); ! 819: ushort rfd_cmd = read_frame[1]; ! 820: ushort next_rx_frame = read_frame[2]; ! 821: ushort data_buffer_addr = read_frame[3]; ! 822: ushort *data_frame = (short *)(dev->mem_start + data_buffer_addr); ! 823: ushort pkt_len = data_frame[0]; ! 824: ! 825: if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 ! 826: || (pkt_len & 0xC000) != 0xC000) { ! 827: printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" ! 828: "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, ! 829: frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, ! 830: pkt_len); ! 831: } else if ((frame_status & 0x2000) == 0) { ! 832: /* Frame Rxed, but with error. */ ! 833: lp->stats.rx_errors++; ! 834: if (frame_status & 0x0800) lp->stats.rx_crc_errors++; ! 835: if (frame_status & 0x0400) lp->stats.rx_frame_errors++; ! 836: if (frame_status & 0x0200) lp->stats.rx_fifo_errors++; ! 837: if (frame_status & 0x0100) lp->stats.rx_over_errors++; ! 838: if (frame_status & 0x0080) lp->stats.rx_length_errors++; ! 839: } else { ! 840: /* Malloc up new buffer. */ ! 841: struct sk_buff *skb; ! 842: ! 843: pkt_len &= 0x3fff; ! 844: skb = dev_alloc_skb(pkt_len+2); ! 845: if (skb == NULL) { ! 846: printk("%s: Memory squeeze, dropping packet.\n", dev->name); ! 847: lp->stats.rx_dropped++; ! 848: break; ! 849: } ! 850: ! 851: skb_reserve(skb,2); ! 852: skb->dev = dev; ! 853: ! 854: /* 'skb->data' points to the start of sk_buff data area. */ ! 855: memcpy(skb_put(skb,pkt_len), data_frame + 5, pkt_len); ! 856: ! 857: skb->protocol=eth_type_trans(skb,dev); ! 858: netif_rx(skb); ! 859: lp->stats.rx_packets++; ! 860: } ! 861: ! 862: /* Clear the status word and set End-of-List on the rx frame. */ ! 863: read_frame[0] = 0; ! 864: read_frame[1] = 0xC000; ! 865: /* Clear the end-of-list on the prev. RFD. */ ! 866: *(short*)(dev->mem_start + rx_tail + 2) = 0x0000; ! 867: ! 868: rx_tail = rx_head; ! 869: rx_head = next_rx_frame; ! 870: if (--boguscount == 0) ! 871: break; ! 872: } ! 873: ! 874: lp->rx_head = rx_head; ! 875: lp->rx_tail = rx_tail; ! 876: } ! 877: #ifdef MODULE ! 878: static char devicename[9] = { 0, }; ! 879: static struct device dev_3c507 = { ! 880: devicename, /* device name is inserted by linux/drivers/net/net_init.c */ ! 881: 0, 0, 0, 0, ! 882: 0, 0, ! 883: 0, 0, 0, NULL, el16_probe ! 884: }; ! 885: ! 886: static int io = 0x300; ! 887: static int irq = 0; ! 888: ! 889: int init_module(void) ! 890: { ! 891: if (io == 0) ! 892: printk("3c507: You should not use auto-probing with insmod!\n"); ! 893: dev_3c507.base_addr = io; ! 894: dev_3c507.irq = irq; ! 895: if (register_netdev(&dev_3c507) != 0) { ! 896: printk("3c507: register_netdev() returned non-zero.\n"); ! 897: return -EIO; ! 898: } ! 899: return 0; ! 900: } ! 901: ! 902: void ! 903: cleanup_module(void) ! 904: { ! 905: unregister_netdev(&dev_3c507); ! 906: kfree(dev_3c507.priv); ! 907: dev_3c507.priv = NULL; ! 908: ! 909: /* If we don't do this, we can't re-insmod it later. */ ! 910: free_irq(dev_3c507.irq, NULL); ! 911: release_region(dev_3c507.base_addr, EL16_IO_EXTENT); ! 912: } ! 913: #endif /* MODULE */ ! 914: ! 915: /* ! 916: * Local variables: ! 917: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c" ! 918: * version-control: t ! 919: * kept-new-versions: 5 ! 920: * tab-width: 4 ! 921: * c-indent-level: 4 ! 922: * End: ! 923: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.