|
|
1.1 ! root 1: /* znet.c: An Zenith Z-Note ethernet driver for linux. */ ! 2: ! 3: static const char *version = "znet.c:v1.02 9/23/94 [email protected]\n"; ! 4: ! 5: /* ! 6: Written by Donald Becker. ! 7: ! 8: The author may be reached as [email protected]. ! 9: This driver is based on the Linux skeleton driver. The copyright of the ! 10: skeleton driver is held by the United States Government, as represented ! 11: by DIRNSA, and it is released under the GPL. ! 12: ! 13: Thanks to Mike Hollick for alpha testing and suggestions. ! 14: ! 15: References: ! 16: The Crynwr packet driver. ! 17: ! 18: "82593 CSMA/CD Core LAN Controller" Intel datasheet, 1992 ! 19: Intel Microcommunications Databook, Vol. 1, 1990. ! 20: As usual with Intel, the documentation is incomplete and inaccurate. ! 21: I had to read the Crynwr packet driver to figure out how to actually ! 22: use the i82593, and guess at what register bits matched the loosely ! 23: related i82586. ! 24: ! 25: Theory of Operation ! 26: ! 27: The i82593 used in the Zenith Z-Note series operates using two(!) slave ! 28: DMA channels, one interrupt, and one 8-bit I/O port. ! 29: ! 30: While there several ways to configure '593 DMA system, I chose the one ! 31: that seemed commensurate with the highest system performance in the face ! 32: of moderate interrupt latency: Both DMA channels are configured as ! 33: recirculating ring buffers, with one channel (#0) dedicated to Rx and ! 34: the other channel (#1) to Tx and configuration. (Note that this is ! 35: different than the Crynwr driver, where the Tx DMA channel is initialized ! 36: before each operation. That approach simplifies operation and Tx error ! 37: recovery, but requires additional I/O in normal operation and precludes ! 38: transmit buffer chaining.) ! 39: ! 40: Both rings are set to 8192 bytes using {TX,RX}_RING_SIZE. This provides ! 41: a reasonable ring size for Rx, while simplifying DMA buffer allocation -- ! 42: DMA buffers must not cross a 128K boundary. (In truth the size selection ! 43: was influenced by my lack of '593 documentation. I thus was constrained ! 44: to use the Crynwr '593 initialization table, which sets the Rx ring size ! 45: to 8K.) ! 46: ! 47: Despite my usual low opinion about Intel-designed parts, I must admit ! 48: that the bulk data handling of the i82593 is a good design for ! 49: an integrated system, like a laptop, where using two slave DMA channels ! 50: doesn't pose a problem. I still take issue with using only a single I/O ! 51: port. In the same controlled environment there are essentially no ! 52: limitations on I/O space, and using multiple locations would eliminate ! 53: the need for multiple operations when looking at status registers, ! 54: setting the Rx ring boundary, or switching to promiscuous mode. ! 55: ! 56: I also question Zenith's selection of the '593: one of the advertised ! 57: advantages of earlier Intel parts was that if you figured out the magic ! 58: initialization incantation you could use the same part on many different ! 59: network types. Zenith's use of the "FriendlyNet" (sic) connector rather ! 60: than an on-board transceiver leads me to believe that they were planning ! 61: to take advantage of this. But, uhmmm, the '593 omits all but ethernet ! 62: functionality from the serial subsystem. ! 63: */ ! 64: ! 65: #include <linux/kernel.h> ! 66: #include <linux/sched.h> ! 67: #include <linux/string.h> ! 68: #include <linux/ptrace.h> ! 69: #include <linux/errno.h> ! 70: #include <linux/interrupt.h> ! 71: #include <linux/ioport.h> ! 72: #include <asm/system.h> ! 73: #include <asm/bitops.h> ! 74: #include <asm/io.h> ! 75: #include <asm/dma.h> ! 76: ! 77: #include <linux/netdevice.h> ! 78: #include <linux/etherdevice.h> ! 79: #include <linux/skbuff.h> ! 80: #include <linux/if_arp.h> ! 81: ! 82: #ifndef ZNET_DEBUG ! 83: #define ZNET_DEBUG 1 ! 84: #endif ! 85: static unsigned int znet_debug = ZNET_DEBUG; ! 86: ! 87: /* The DMA modes we need aren't in <dma.h>. */ ! 88: #define DMA_RX_MODE 0x14 /* Auto init, I/O to mem, ++, demand. */ ! 89: #define DMA_TX_MODE 0x18 /* Auto init, Mem to I/O, ++, demand. */ ! 90: #define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17) ! 91: #define DMA_BUF_SIZE 8192 ! 92: #define RX_BUF_SIZE 8192 ! 93: #define TX_BUF_SIZE 8192 ! 94: ! 95: /* Commands to the i82593 channel 0. */ ! 96: #define CMD0_CHNL_0 0x00 ! 97: #define CMD0_CHNL_1 0x10 /* Switch to channel 1. */ ! 98: #define CMD0_NOP (CMD0_CHNL_0) ! 99: #define CMD0_PORT_1 CMD0_CHNL_1 ! 100: #define CMD1_PORT_0 1 ! 101: #define CMD0_IA_SETUP 1 ! 102: #define CMD0_CONFIGURE 2 ! 103: #define CMD0_MULTICAST_LIST 3 ! 104: #define CMD0_TRANSMIT 4 ! 105: #define CMD0_DUMP 6 ! 106: #define CMD0_DIAGNOSE 7 ! 107: #define CMD0_Rx_ENABLE 8 ! 108: #define CMD0_Rx_DISABLE 10 ! 109: #define CMD0_Rx_STOP 11 ! 110: #define CMD0_RETRANSMIT 12 ! 111: #define CMD0_ABORT 13 ! 112: #define CMD0_RESET 14 ! 113: ! 114: #define CMD0_ACK 0x80 ! 115: ! 116: #define CMD0_STAT0 (0 << 5) ! 117: #define CMD0_STAT1 (1 << 5) ! 118: #define CMD0_STAT2 (2 << 5) ! 119: #define CMD0_STAT3 (3 << 5) ! 120: ! 121: #define net_local znet_private ! 122: struct znet_private { ! 123: int rx_dma, tx_dma; ! 124: struct enet_statistics stats; ! 125: /* The starting, current, and end pointers for the packet buffers. */ ! 126: ushort *rx_start, *rx_cur, *rx_end; ! 127: ushort *tx_start, *tx_cur, *tx_end; ! 128: ushort tx_buf_len; /* Tx buffer length, in words. */ ! 129: }; ! 130: ! 131: /* Only one can be built-in;-> */ ! 132: static struct znet_private zn; ! 133: static ushort dma_buffer1[DMA_BUF_SIZE/2]; ! 134: static ushort dma_buffer2[DMA_BUF_SIZE/2]; ! 135: static ushort dma_buffer3[DMA_BUF_SIZE/2 + 8]; ! 136: ! 137: /* The configuration block. What an undocumented nightmare. The first ! 138: set of values are those suggested (without explanation) for ethernet ! 139: in the Intel 82586 databook. The rest appear to be completely undocumented, ! 140: except for cryptic notes in the Crynwr packet driver. This driver uses ! 141: the Crynwr values verbatim. */ ! 142: ! 143: static unsigned char i593_init[] = { ! 144: 0xAA, /* 0: 16-byte input & 80-byte output FIFO. */ ! 145: /* threshold, 96-byte FIFO, 82593 mode. */ ! 146: 0x88, /* 1: Continuous w/interrupts, 128-clock DMA.*/ ! 147: 0x2E, /* 2: 8-byte preamble, NO address insertion, */ ! 148: /* 6-byte Ethernet address, loopback off.*/ ! 149: 0x00, /* 3: Default priorities & backoff methods. */ ! 150: 0x60, /* 4: 96-bit interframe spacing. */ ! 151: 0x00, /* 5: 512-bit slot time (low-order). */ ! 152: 0xF2, /* 6: Slot time (high-order), 15 COLL retries. */ ! 153: 0x00, /* 7: Promisc-off, broadcast-on, default CRC. */ ! 154: 0x00, /* 8: Default carrier-sense, collision-detect. */ ! 155: 0x40, /* 9: 64-byte minimum frame length. */ ! 156: 0x5F, /* A: Type/length checks OFF, no CRC input, ! 157: "jabber" termination, etc. */ ! 158: 0x00, /* B: Full-duplex disabled. */ ! 159: 0x3F, /* C: Default multicast addresses & backoff. */ ! 160: 0x07, /* D: Default IFS retriggering. */ ! 161: 0x31, /* E: Internal retransmit, drop "runt" packets, ! 162: synchr. DRQ deassertion, 6 status bytes. */ ! 163: 0x22, /* F: Receive ring-buffer size (8K), ! 164: receive-stop register enable. */ ! 165: }; ! 166: ! 167: struct netidblk { ! 168: char magic[8]; /* The magic number (string) "NETIDBLK" */ ! 169: unsigned char netid[8]; /* The physical station address */ ! 170: char nettype, globalopt; ! 171: char vendor[8]; /* The machine vendor and product name. */ ! 172: char product[8]; ! 173: char irq1, irq2; /* Interrupts, only one is currently used. */ ! 174: char dma1, dma2; ! 175: short dma_mem_misc[8]; /* DMA buffer locations (unused in Linux). */ ! 176: short iobase1, iosize1; ! 177: short iobase2, iosize2; /* Second iobase unused. */ ! 178: char driver_options; /* Misc. bits */ ! 179: char pad; ! 180: }; ! 181: ! 182: int znet_probe(struct device *dev); ! 183: static int znet_open(struct device *dev); ! 184: static int znet_send_packet(struct sk_buff *skb, struct device *dev); ! 185: static void znet_interrupt(int irq, void *dev_id, struct pt_regs *regs); ! 186: static void znet_rx(struct device *dev); ! 187: static int znet_close(struct device *dev); ! 188: static struct enet_statistics *net_get_stats(struct device *dev); ! 189: static void set_multicast_list(struct device *dev); ! 190: static void hardware_init(struct device *dev); ! 191: static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset); ! 192: ! 193: #ifdef notdef ! 194: static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, }; ! 195: #endif ! 196: ! 197: ! 198: /* The Z-Note probe is pretty easy. The NETIDBLK exists in the safe-to-probe ! 199: BIOS area. We just scan for the signature, and pull the vital parameters ! 200: out of the structure. */ ! 201: ! 202: int znet_probe(struct device *dev) ! 203: { ! 204: int i; ! 205: struct netidblk *netinfo; ! 206: char *p; ! 207: ! 208: /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ ! 209: for(p = (char *)0xf0000; p < (char *)0x100000; p++) ! 210: if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0) ! 211: break; ! 212: ! 213: if (p >= (char *)0x100000) { ! 214: if (znet_debug > 1) ! 215: printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); ! 216: return ENODEV; ! 217: } ! 218: netinfo = (struct netidblk *)p; ! 219: dev->base_addr = netinfo->iobase1; ! 220: dev->irq = netinfo->irq1; ! 221: ! 222: printk(KERN_INFO "%s: ZNET at %#3lx,", dev->name, dev->base_addr); ! 223: ! 224: /* The station address is in the "netidblk" at 0x0f0000. */ ! 225: for (i = 0; i < 6; i++) ! 226: printk(" %2.2x", dev->dev_addr[i] = netinfo->netid[i]); ! 227: ! 228: printk(", using IRQ %d DMA %d and %d.\n", dev->irq, netinfo->dma1, ! 229: netinfo->dma2); ! 230: ! 231: if (znet_debug > 1) { ! 232: printk(KERN_INFO "%s: vendor '%16.16s' IRQ1 %d IRQ2 %d DMA1 %d DMA2 %d.\n", ! 233: dev->name, netinfo->vendor, ! 234: netinfo->irq1, netinfo->irq2, ! 235: netinfo->dma1, netinfo->dma2); ! 236: printk(KERN_INFO "%s: iobase1 %#x size %d iobase2 %#x size %d net type %2.2x.\n", ! 237: dev->name, netinfo->iobase1, netinfo->iosize1, ! 238: netinfo->iobase2, netinfo->iosize2, netinfo->nettype); ! 239: } ! 240: ! 241: if (znet_debug > 0) ! 242: printk("%s%s", KERN_INFO, version); ! 243: ! 244: dev->priv = (void *) &zn; ! 245: zn.rx_dma = netinfo->dma1; ! 246: zn.tx_dma = netinfo->dma2; ! 247: ! 248: /* These should never fail. You can't add devices to a sealed box! */ ! 249: if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", NULL) ! 250: || request_dma(zn.rx_dma,"ZNet rx") ! 251: || request_dma(zn.tx_dma,"ZNet tx")) { ! 252: printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name); ! 253: return EBUSY; ! 254: } ! 255: irq2dev_map[dev->irq] = dev; ! 256: ! 257: /* Allocate buffer memory. We can cross a 128K boundary, so we ! 258: must be careful about the allocation. It's easiest to waste 8K. */ ! 259: if (dma_page_eq(dma_buffer1, &dma_buffer1[RX_BUF_SIZE/2-1])) ! 260: zn.rx_start = dma_buffer1; ! 261: else ! 262: zn.rx_start = dma_buffer2; ! 263: ! 264: if (dma_page_eq(dma_buffer3, &dma_buffer3[RX_BUF_SIZE/2-1])) ! 265: zn.tx_start = dma_buffer3; ! 266: else ! 267: zn.tx_start = dma_buffer2; ! 268: zn.rx_end = zn.rx_start + RX_BUF_SIZE/2; ! 269: zn.tx_buf_len = TX_BUF_SIZE/2; ! 270: zn.tx_end = zn.tx_start + zn.tx_buf_len; ! 271: ! 272: /* The ZNET-specific entries in the device structure. */ ! 273: dev->open = &znet_open; ! 274: dev->hard_start_xmit = &znet_send_packet; ! 275: dev->stop = &znet_close; ! 276: dev->get_stats = net_get_stats; ! 277: dev->set_multicast_list = &set_multicast_list; ! 278: ! 279: /* Fill in the 'dev' with ethernet-generic values. */ ! 280: ether_setup(dev); ! 281: ! 282: return 0; ! 283: } ! 284: ! 285: ! 286: static int znet_open(struct device *dev) ! 287: { ! 288: int ioaddr = dev->base_addr; ! 289: ! 290: if (znet_debug > 2) ! 291: printk(KERN_DEBUG "%s: znet_open() called.\n", dev->name); ! 292: ! 293: /* Turn on the 82501 SIA, using zenith-specific magic. */ ! 294: outb(0x10, 0xe6); /* Select LAN control register */ ! 295: outb(inb(0xe7) | 0x84, 0xe7); /* Turn on LAN power (bit 2). */ ! 296: /* According to the Crynwr driver we should wait 50 msec. for the ! 297: LAN clock to stabilize. My experiments indicates that the '593 can ! 298: be initialized immediately. The delay is probably needed for the ! 299: DC-to-DC converter to come up to full voltage, and for the oscillator ! 300: to be spot-on at 20Mhz before transmitting. ! 301: Until this proves to be a problem we rely on the higher layers for the ! 302: delay and save allocating a timer entry. */ ! 303: ! 304: /* This follows the packet driver's lead, and checks for success. */ ! 305: if (inb(ioaddr) != 0x10 && inb(ioaddr) != 0x00) ! 306: printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n", ! 307: dev->name); ! 308: ! 309: dev->tbusy = 0; ! 310: dev->interrupt = 0; ! 311: hardware_init(dev); ! 312: dev->start = 1; ! 313: ! 314: return 0; ! 315: } ! 316: ! 317: static int znet_send_packet(struct sk_buff *skb, struct device *dev) ! 318: { ! 319: int ioaddr = dev->base_addr; ! 320: ! 321: if (znet_debug > 4) ! 322: printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy); ! 323: ! 324: /* Transmitter timeout, likely just recovery after suspending the machine. */ ! 325: if (dev->tbusy) { ! 326: ushort event, tx_status, rx_offset, state; ! 327: int tickssofar = jiffies - dev->trans_start; ! 328: if (tickssofar < 10) ! 329: return 1; ! 330: outb(CMD0_STAT0, ioaddr); event = inb(ioaddr); ! 331: outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr); ! 332: outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr); ! 333: outb(CMD0_STAT3, ioaddr); state = inb(ioaddr); ! 334: printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," ! 335: " resetting.\n", dev->name, event, tx_status, rx_offset, state); ! 336: if (tx_status == 0x0400) ! 337: printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", ! 338: dev->name); ! 339: outb(CMD0_RESET, ioaddr); ! 340: hardware_init(dev); ! 341: } ! 342: ! 343: if (skb == NULL) { ! 344: dev_tint(dev); ! 345: return 0; ! 346: } ! 347: ! 348: /* Check that the part hasn't reset itself, probably from suspend. */ ! 349: outb(CMD0_STAT0, ioaddr); ! 350: if (inw(ioaddr) == 0x0010 ! 351: && inw(ioaddr) == 0x0000 ! 352: && inw(ioaddr) == 0x0010) ! 353: hardware_init(dev); ! 354: ! 355: /* Block a timer-based transmit from overlapping. This could better be ! 356: done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ ! 357: if (set_bit(0, (void*)&dev->tbusy) != 0) ! 358: printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); ! 359: else { ! 360: short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; ! 361: unsigned char *buf = (void *)skb->data; ! 362: ushort *tx_link = zn.tx_cur - 1; ! 363: ushort rnd_len = (length + 1)>>1; ! 364: ! 365: { ! 366: short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE; ! 367: unsigned addr = inb(dma_port); ! 368: addr |= inb(dma_port) << 8; ! 369: addr <<= 1; ! 370: if (((int)zn.tx_cur & 0x1ffff) != addr) ! 371: printk(KERN_WARNING "Address mismatch at Tx: %#x vs %#x.\n", ! 372: (int)zn.tx_cur & 0xffff, addr); ! 373: zn.tx_cur = (ushort *)(((int)zn.tx_cur & 0xfe0000) | addr); ! 374: } ! 375: ! 376: if (zn.tx_cur >= zn.tx_end) ! 377: zn.tx_cur = zn.tx_start; ! 378: *zn.tx_cur++ = length; ! 379: if (zn.tx_cur + rnd_len + 1 > zn.tx_end) { ! 380: int semi_cnt = (zn.tx_end - zn.tx_cur)<<1; /* Cvrt to byte cnt. */ ! 381: memcpy(zn.tx_cur, buf, semi_cnt); ! 382: rnd_len -= semi_cnt>>1; ! 383: memcpy(zn.tx_start, buf + semi_cnt, length - semi_cnt); ! 384: zn.tx_cur = zn.tx_start + rnd_len; ! 385: } else { ! 386: memcpy(zn.tx_cur, buf, skb->len); ! 387: zn.tx_cur += rnd_len; ! 388: } ! 389: *zn.tx_cur++ = 0; ! 390: cli(); { ! 391: *tx_link = CMD0_TRANSMIT + CMD0_CHNL_1; ! 392: /* Is this always safe to do? */ ! 393: outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr); ! 394: } sti(); ! 395: ! 396: dev->trans_start = jiffies; ! 397: if (znet_debug > 4) ! 398: printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length); ! 399: } ! 400: dev_kfree_skb(skb, FREE_WRITE); ! 401: return 0; ! 402: } ! 403: ! 404: /* The ZNET interrupt handler. */ ! 405: static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs) ! 406: { ! 407: struct device *dev = irq2dev_map[irq]; ! 408: int ioaddr; ! 409: int boguscnt = 20; ! 410: ! 411: if (dev == NULL) { ! 412: printk(KERN_WARNING "znet_interrupt(): IRQ %d for unknown device.\n", irq); ! 413: return; ! 414: } ! 415: ! 416: dev->interrupt = 1; ! 417: ioaddr = dev->base_addr; ! 418: ! 419: outb(CMD0_STAT0, ioaddr); ! 420: do { ! 421: ushort status = inb(ioaddr); ! 422: if (znet_debug > 5) { ! 423: ushort result, rx_ptr, running; ! 424: outb(CMD0_STAT1, ioaddr); ! 425: result = inw(ioaddr); ! 426: outb(CMD0_STAT2, ioaddr); ! 427: rx_ptr = inw(ioaddr); ! 428: outb(CMD0_STAT3, ioaddr); ! 429: running = inb(ioaddr); ! 430: printk(KERN_DEBUG "%s: interrupt, status %02x, %04x %04x %02x serial %d.\n", ! 431: dev->name, status, result, rx_ptr, running, boguscnt); ! 432: } ! 433: if ((status & 0x80) == 0) ! 434: break; ! 435: ! 436: if ((status & 0x0F) == 4) { /* Transmit done. */ ! 437: struct net_local *lp = (struct net_local *)dev->priv; ! 438: int tx_status; ! 439: outb(CMD0_STAT1, ioaddr); ! 440: tx_status = inw(ioaddr); ! 441: /* It's undocumented, but tx_status seems to match the i82586. */ ! 442: if (tx_status & 0x2000) { ! 443: lp->stats.tx_packets++; ! 444: lp->stats.collisions += tx_status & 0xf; ! 445: } else { ! 446: if (tx_status & 0x0600) lp->stats.tx_carrier_errors++; ! 447: if (tx_status & 0x0100) lp->stats.tx_fifo_errors++; ! 448: if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; ! 449: if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; ! 450: /* ...and the catch-all. */ ! 451: if ((tx_status | 0x0760) != 0x0760) ! 452: lp->stats.tx_errors++; ! 453: } ! 454: dev->tbusy = 0; ! 455: mark_bh(NET_BH); /* Inform upper layers. */ ! 456: } ! 457: ! 458: if ((status & 0x40) ! 459: || (status & 0x0f) == 11) { ! 460: znet_rx(dev); ! 461: } ! 462: /* Clear the interrupts we've handled. */ ! 463: outb(CMD0_ACK,ioaddr); ! 464: } while (boguscnt--); ! 465: ! 466: dev->interrupt = 0; ! 467: return; ! 468: } ! 469: ! 470: static void znet_rx(struct device *dev) ! 471: { ! 472: struct net_local *lp = (struct net_local *)dev->priv; ! 473: int ioaddr = dev->base_addr; ! 474: int boguscount = 1; ! 475: short next_frame_end_offset = 0; /* Offset of next frame start. */ ! 476: short *cur_frame_end; ! 477: short cur_frame_end_offset; ! 478: ! 479: outb(CMD0_STAT2, ioaddr); ! 480: cur_frame_end_offset = inw(ioaddr); ! 481: ! 482: if (cur_frame_end_offset == zn.rx_cur - zn.rx_start) { ! 483: printk(KERN_WARNING "%s: Interrupted, but nothing to receive, offset %03x.\n", ! 484: dev->name, cur_frame_end_offset); ! 485: return; ! 486: } ! 487: ! 488: /* Use same method as the Crynwr driver: construct a forward list in ! 489: the same area of the backwards links we now have. This allows us to ! 490: pass packets to the upper layers in the order they were received -- ! 491: important for fast-path sequential operations. */ ! 492: while (zn.rx_start + cur_frame_end_offset != zn.rx_cur ! 493: && ++boguscount < 5) { ! 494: unsigned short hi_cnt, lo_cnt, hi_status, lo_status; ! 495: int count, status; ! 496: ! 497: if (cur_frame_end_offset < 4) { ! 498: /* Oh no, we have a special case: the frame trailer wraps around ! 499: the end of the ring buffer. We've saved space at the end of ! 500: the ring buffer for just this problem. */ ! 501: memcpy(zn.rx_end, zn.rx_start, 8); ! 502: cur_frame_end_offset += (RX_BUF_SIZE/2); ! 503: } ! 504: cur_frame_end = zn.rx_start + cur_frame_end_offset - 4; ! 505: ! 506: lo_status = *cur_frame_end++; ! 507: hi_status = *cur_frame_end++; ! 508: status = ((hi_status & 0xff) << 8) + (lo_status & 0xff); ! 509: lo_cnt = *cur_frame_end++; ! 510: hi_cnt = *cur_frame_end++; ! 511: count = ((hi_cnt & 0xff) << 8) + (lo_cnt & 0xff); ! 512: ! 513: if (znet_debug > 5) ! 514: printk(KERN_DEBUG "Constructing trailer at location %03x, %04x %04x %04x %04x" ! 515: " count %#x status %04x.\n", ! 516: cur_frame_end_offset<<1, lo_status, hi_status, lo_cnt, hi_cnt, ! 517: count, status); ! 518: cur_frame_end[-4] = status; ! 519: cur_frame_end[-3] = next_frame_end_offset; ! 520: cur_frame_end[-2] = count; ! 521: next_frame_end_offset = cur_frame_end_offset; ! 522: cur_frame_end_offset -= ((count + 1)>>1) + 3; ! 523: if (cur_frame_end_offset < 0) ! 524: cur_frame_end_offset += RX_BUF_SIZE/2; ! 525: }; ! 526: ! 527: /* Now step forward through the list. */ ! 528: do { ! 529: ushort *this_rfp_ptr = zn.rx_start + next_frame_end_offset; ! 530: int status = this_rfp_ptr[-4]; ! 531: int pkt_len = this_rfp_ptr[-2]; ! 532: ! 533: if (znet_debug > 5) ! 534: printk(KERN_DEBUG "Looking at trailer ending at %04x status %04x length %03x" ! 535: " next %04x.\n", next_frame_end_offset<<1, status, pkt_len, ! 536: this_rfp_ptr[-3]<<1); ! 537: /* Once again we must assume that the i82586 docs apply. */ ! 538: if ( ! (status & 0x2000)) { /* There was an error. */ ! 539: lp->stats.rx_errors++; ! 540: if (status & 0x0800) lp->stats.rx_crc_errors++; ! 541: if (status & 0x0400) lp->stats.rx_frame_errors++; ! 542: if (status & 0x0200) lp->stats.rx_over_errors++; /* Wrong. */ ! 543: if (status & 0x0100) lp->stats.rx_fifo_errors++; ! 544: if (status & 0x0080) lp->stats.rx_length_errors++; ! 545: } else if (pkt_len > 1536) { ! 546: lp->stats.rx_length_errors++; ! 547: } else { ! 548: /* Malloc up new buffer. */ ! 549: struct sk_buff *skb; ! 550: ! 551: skb = dev_alloc_skb(pkt_len); ! 552: if (skb == NULL) { ! 553: if (znet_debug) ! 554: printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); ! 555: lp->stats.rx_dropped++; ! 556: break; ! 557: } ! 558: skb->dev = dev; ! 559: ! 560: if (&zn.rx_cur[(pkt_len+1)>>1] > zn.rx_end) { ! 561: int semi_cnt = (zn.rx_end - zn.rx_cur)<<1; ! 562: memcpy(skb_put(skb,semi_cnt), zn.rx_cur, semi_cnt); ! 563: memcpy(skb_put(skb,pkt_len-semi_cnt), zn.rx_start, ! 564: pkt_len - semi_cnt); ! 565: } else { ! 566: memcpy(skb_put(skb,pkt_len), zn.rx_cur, pkt_len); ! 567: if (znet_debug > 6) { ! 568: unsigned int *packet = (unsigned int *) skb->data; ! 569: printk(KERN_DEBUG "Packet data is %08x %08x %08x %08x.\n", packet[0], ! 570: packet[1], packet[2], packet[3]); ! 571: } ! 572: } ! 573: skb->protocol=eth_type_trans(skb,dev); ! 574: netif_rx(skb); ! 575: lp->stats.rx_packets++; ! 576: } ! 577: zn.rx_cur = this_rfp_ptr; ! 578: if (zn.rx_cur >= zn.rx_end) ! 579: zn.rx_cur -= RX_BUF_SIZE/2; ! 580: update_stop_hit(ioaddr, (zn.rx_cur - zn.rx_start)<<1); ! 581: next_frame_end_offset = this_rfp_ptr[-3]; ! 582: if (next_frame_end_offset == 0) /* Read all the frames? */ ! 583: break; /* Done for now */ ! 584: this_rfp_ptr = zn.rx_start + next_frame_end_offset; ! 585: } while (--boguscount); ! 586: ! 587: /* If any worth-while packets have been received, dev_rint() ! 588: has done a mark_bh(INET_BH) for us and will work on them ! 589: when we get to the bottom-half routine. */ ! 590: return; ! 591: } ! 592: ! 593: /* The inverse routine to znet_open(). */ ! 594: static int znet_close(struct device *dev) ! 595: { ! 596: int ioaddr = dev->base_addr; ! 597: ! 598: dev->tbusy = 1; ! 599: dev->start = 0; ! 600: ! 601: outb(CMD0_RESET, ioaddr); /* CMD0_RESET */ ! 602: ! 603: disable_dma(zn.rx_dma); ! 604: disable_dma(zn.tx_dma); ! 605: ! 606: free_irq(dev->irq, NULL); ! 607: ! 608: if (znet_debug > 1) ! 609: printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); ! 610: /* Turn off transceiver power. */ ! 611: outb(0x10, 0xe6); /* Select LAN control register */ ! 612: outb(inb(0xe7) & ~0x84, 0xe7); /* Turn on LAN power (bit 2). */ ! 613: ! 614: return 0; ! 615: } ! 616: ! 617: /* Get the current statistics. This may be called with the card open or ! 618: closed. */ ! 619: static struct enet_statistics *net_get_stats(struct device *dev) ! 620: { ! 621: struct net_local *lp = (struct net_local *)dev->priv; ! 622: ! 623: return &lp->stats; ! 624: } ! 625: ! 626: /* Set or clear the multicast filter for this adaptor. ! 627: As a side effect this routine must also initialize the device parameters. ! 628: This is taken advantage of in open(). ! 629: ! 630: N.B. that we change i593_init[] in place. This (properly) makes the ! 631: mode change persistent, but must be changed if this code is moved to ! 632: a multiple adaptor environment. ! 633: */ ! 634: static void set_multicast_list(struct device *dev) ! 635: { ! 636: short ioaddr = dev->base_addr; ! 637: ! 638: if (dev->flags&IFF_PROMISC) { ! 639: /* Enable promiscuous mode */ ! 640: i593_init[7] &= ~3; i593_init[7] |= 1; ! 641: i593_init[13] &= ~8; i593_init[13] |= 8; ! 642: } else if (dev->mc_list || (dev->flags&IFF_ALLMULTI)) { ! 643: /* Enable accept-all-multicast mode */ ! 644: i593_init[7] &= ~3; i593_init[7] |= 0; ! 645: i593_init[13] &= ~8; i593_init[13] |= 8; ! 646: } else { /* Enable normal mode. */ ! 647: i593_init[7] &= ~3; i593_init[7] |= 0; ! 648: i593_init[13] &= ~8; i593_init[13] |= 0; ! 649: } ! 650: *zn.tx_cur++ = sizeof(i593_init); ! 651: memcpy(zn.tx_cur, i593_init, sizeof(i593_init)); ! 652: zn.tx_cur += sizeof(i593_init)/2; ! 653: outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); ! 654: #ifdef not_tested ! 655: if (num_addrs > 0) { ! 656: int addrs_len = 6*num_addrs; ! 657: *zn.tx_cur++ = addrs_len; ! 658: memcpy(zn.tx_cur, addrs, addrs_len); ! 659: outb(CMD0_MULTICAST_LIST+CMD0_CHNL_1, ioaddr); ! 660: zn.tx_cur += addrs_len>>1; ! 661: } ! 662: #endif ! 663: } ! 664: ! 665: void show_dma(void) ! 666: { ! 667: short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE; ! 668: unsigned addr = inb(dma_port); ! 669: addr |= inb(dma_port) << 8; ! 670: printk("Addr: %04x cnt:%3x...", addr<<1, get_dma_residue(zn.tx_dma)); ! 671: } ! 672: ! 673: /* Initialize the hardware. We have to do this when the board is open()ed ! 674: or when we come out of suspend mode. */ ! 675: static void hardware_init(struct device *dev) ! 676: { ! 677: short ioaddr = dev->base_addr; ! 678: ! 679: zn.rx_cur = zn.rx_start; ! 680: zn.tx_cur = zn.tx_start; ! 681: ! 682: /* Reset the chip, and start it up. */ ! 683: outb(CMD0_RESET, ioaddr); ! 684: ! 685: cli(); { /* Protect against a DMA flip-flop */ ! 686: disable_dma(zn.rx_dma); /* reset by an interrupting task. */ ! 687: clear_dma_ff(zn.rx_dma); ! 688: set_dma_mode(zn.rx_dma, DMA_RX_MODE); ! 689: set_dma_addr(zn.rx_dma, (unsigned int) zn.rx_start); ! 690: set_dma_count(zn.rx_dma, RX_BUF_SIZE); ! 691: enable_dma(zn.rx_dma); ! 692: /* Now set up the Tx channel. */ ! 693: disable_dma(zn.tx_dma); ! 694: clear_dma_ff(zn.tx_dma); ! 695: set_dma_mode(zn.tx_dma, DMA_TX_MODE); ! 696: set_dma_addr(zn.tx_dma, (unsigned int) zn.tx_start); ! 697: set_dma_count(zn.tx_dma, zn.tx_buf_len<<1); ! 698: enable_dma(zn.tx_dma); ! 699: } sti(); ! 700: ! 701: if (znet_debug > 1) ! 702: printk(KERN_DEBUG "%s: Initializing the i82593, tx buf %p... ", dev->name, ! 703: zn.tx_start); ! 704: /* Do an empty configure command, just like the Crynwr driver. This ! 705: resets to chip to its default values. */ ! 706: *zn.tx_cur++ = 0; ! 707: *zn.tx_cur++ = 0; ! 708: printk("stat:%02x ", inb(ioaddr)); show_dma(); ! 709: outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); ! 710: *zn.tx_cur++ = sizeof(i593_init); ! 711: memcpy(zn.tx_cur, i593_init, sizeof(i593_init)); ! 712: zn.tx_cur += sizeof(i593_init)/2; ! 713: printk("stat:%02x ", inb(ioaddr)); show_dma(); ! 714: outb(CMD0_CONFIGURE+CMD0_CHNL_1, ioaddr); ! 715: *zn.tx_cur++ = 6; ! 716: memcpy(zn.tx_cur, dev->dev_addr, 6); ! 717: zn.tx_cur += 3; ! 718: printk("stat:%02x ", inb(ioaddr)); show_dma(); ! 719: outb(CMD0_IA_SETUP + CMD0_CHNL_1, ioaddr); ! 720: printk("stat:%02x ", inb(ioaddr)); show_dma(); ! 721: ! 722: update_stop_hit(ioaddr, 8192); ! 723: if (znet_debug > 1) printk("enabling Rx.\n"); ! 724: outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr); ! 725: dev->tbusy = 0; ! 726: } ! 727: ! 728: static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset) ! 729: { ! 730: outb(CMD0_PORT_1, ioaddr); ! 731: if (znet_debug > 5) ! 732: printk(KERN_DEBUG "Updating stop hit with value %02x.\n", ! 733: (rx_stop_offset >> 6) | 0x80); ! 734: outb((rx_stop_offset >> 6) | 0x80, ioaddr); ! 735: outb(CMD1_PORT_0, ioaddr); ! 736: } ! 737: ! 738: /* ! 739: * Local variables: ! 740: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c znet.c" ! 741: * version-control: t ! 742: * kept-new-versions: 5 ! 743: * c-indent-level: 4 ! 744: * tab-width: 4 ! 745: * End: ! 746: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.