|
|
1.1 ! root 1: /* apricot.c: An Apricot 82596 ethernet driver for linux. */ ! 2: /* ! 3: Apricot ! 4: Written 1994 by Mark Evans. ! 5: This driver is for the Apricot 82596 bus-master interface ! 6: ! 7: Modularised 12/94 Mark Evans ! 8: ! 9: Driver skeleton ! 10: Written 1993 by Donald Becker. ! 11: Copyright 1993 United States Government as represented by the Director, ! 12: National Security Agency. This software may only be used and distributed ! 13: according to the terms of the GNU Public License as modified by SRC, ! 14: incorporated herein by reference. ! 15: ! 16: The author may be reached as [email protected] or ! 17: C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 ! 18: ! 19: ! 20: */ ! 21: ! 22: static const char *version = "apricot.c:v0.2 05/12/94\n"; ! 23: ! 24: #include <linux/module.h> ! 25: ! 26: #include <linux/kernel.h> ! 27: #include <linux/sched.h> ! 28: #include <linux/string.h> ! 29: #include <linux/ptrace.h> ! 30: #include <linux/errno.h> ! 31: #include <linux/ioport.h> ! 32: #include <linux/malloc.h> ! 33: #include <linux/interrupt.h> ! 34: #include <linux/netdevice.h> ! 35: #include <linux/etherdevice.h> ! 36: #include <linux/skbuff.h> ! 37: ! 38: #include <asm/bitops.h> ! 39: #include <asm/io.h> ! 40: #include <asm/dma.h> ! 41: ! 42: #ifndef HAVE_PORTRESERVE ! 43: #define check_region(addr, size) 0 ! 44: #define request_region(addr, size,name) do ; while(0) ! 45: #endif ! 46: ! 47: #ifndef HAVE_ALLOC_SKB ! 48: #define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority) ! 49: #define kfree_skbmem(buff, size) kfree_s(buff,size) ! 50: #endif ! 51: ! 52: #define APRICOT_DEBUG 1 ! 53: ! 54: #ifdef APRICOT_DEBUG ! 55: int i596_debug = APRICOT_DEBUG; ! 56: #else ! 57: int i596_debug = 1; ! 58: #endif ! 59: ! 60: #define APRICOT_TOTAL_SIZE 17 ! 61: ! 62: #define I596_NULL -1 ! 63: ! 64: #define CMD_EOL 0x8000 /* The last command of the list, stop. */ ! 65: #define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ ! 66: #define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ ! 67: ! 68: #define CMD_FLEX 0x0008 /* Enable flexible memory model */ ! 69: ! 70: enum commands { ! 71: CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, ! 72: CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; ! 73: ! 74: #define STAT_C 0x8000 /* Set to 0 after execution */ ! 75: #define STAT_B 0x4000 /* Command being executed */ ! 76: #define STAT_OK 0x2000 /* Command executed ok */ ! 77: #define STAT_A 0x1000 /* Command aborted */ ! 78: ! 79: #define CUC_START 0x0100 ! 80: #define CUC_RESUME 0x0200 ! 81: #define CUC_SUSPEND 0x0300 ! 82: #define CUC_ABORT 0x0400 ! 83: #define RX_START 0x0010 ! 84: #define RX_RESUME 0x0020 ! 85: #define RX_SUSPEND 0x0030 ! 86: #define RX_ABORT 0x0040 ! 87: ! 88: struct i596_cmd { ! 89: unsigned short status; ! 90: unsigned short command; ! 91: struct i596_cmd *next; ! 92: }; ! 93: ! 94: #define EOF 0x8000 ! 95: #define SIZE_MASK 0x3fff ! 96: ! 97: struct i596_tbd { ! 98: unsigned short size; ! 99: unsigned short pad; ! 100: struct i596_tbd *next; ! 101: char *data; ! 102: }; ! 103: ! 104: struct tx_cmd { ! 105: struct i596_cmd cmd; ! 106: struct i596_tbd *tbd; ! 107: unsigned short size; ! 108: unsigned short pad; ! 109: }; ! 110: ! 111: struct i596_rfd { ! 112: unsigned short stat; ! 113: unsigned short cmd; ! 114: struct i596_rfd *next; ! 115: long rbd; ! 116: unsigned short count; ! 117: unsigned short size; ! 118: char data[1532]; ! 119: }; ! 120: ! 121: #define RX_RING_SIZE 8 ! 122: ! 123: struct i596_scb { ! 124: unsigned short status; ! 125: unsigned short command; ! 126: struct i596_cmd *cmd; ! 127: struct i596_rfd *rfd; ! 128: unsigned long crc_err; ! 129: unsigned long align_err; ! 130: unsigned long resource_err; ! 131: unsigned long over_err; ! 132: unsigned long rcvdt_err; ! 133: unsigned long short_err; ! 134: unsigned short t_on; ! 135: unsigned short t_off; ! 136: }; ! 137: ! 138: struct i596_iscp { ! 139: unsigned long stat; ! 140: struct i596_scb *scb; ! 141: }; ! 142: ! 143: struct i596_scp { ! 144: unsigned long sysbus; ! 145: unsigned long pad; ! 146: struct i596_iscp *iscp; ! 147: }; ! 148: ! 149: struct i596_private { ! 150: volatile struct i596_scp scp; ! 151: volatile struct i596_iscp iscp; ! 152: volatile struct i596_scb scb; ! 153: volatile struct i596_cmd set_add; ! 154: char eth_addr[8]; ! 155: volatile struct i596_cmd set_conf; ! 156: char i596_config[16]; ! 157: volatile struct i596_cmd tdr; ! 158: unsigned long stat; ! 159: int last_restart; ! 160: struct i596_rfd *rx_tail; ! 161: struct i596_cmd *cmd_tail; ! 162: struct i596_cmd *cmd_head; ! 163: int cmd_backlog; ! 164: unsigned long last_cmd; ! 165: struct enet_statistics stats; ! 166: }; ! 167: ! 168: char init_setup[] = { ! 169: 0x8E, /* length, prefetch on */ ! 170: 0xC8, /* fifo to 8, monitor off */ ! 171: 0x80, /* don't save bad frames */ ! 172: 0x2E, /* No source address insertion, 8 byte preamble */ ! 173: 0x00, /* priority and backoff defaults */ ! 174: 0x60, /* interframe spacing */ ! 175: 0x00, /* slot time LSB */ ! 176: 0xf2, /* slot time and retries */ ! 177: 0x00, /* promiscuous mode */ ! 178: 0x00, /* collision detect */ ! 179: 0x40, /* minimum frame length */ ! 180: 0xff, ! 181: 0x00, ! 182: 0x7f /* *multi IA */ }; ! 183: ! 184: static int i596_open(struct device *dev); ! 185: static int i596_start_xmit(struct sk_buff *skb, struct device *dev); ! 186: static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs); ! 187: static int i596_close(struct device *dev); ! 188: static struct enet_statistics *i596_get_stats(struct device *dev); ! 189: static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd); ! 190: static void print_eth(char *); ! 191: static void set_multicast_list(struct device *dev); ! 192: ! 193: ! 194: static inline int ! 195: init_rx_bufs(struct device *dev, int num) ! 196: { ! 197: struct i596_private *lp = (struct i596_private *)dev->priv; ! 198: int i; ! 199: struct i596_rfd *rfd; ! 200: ! 201: lp->scb.rfd = (struct i596_rfd *)I596_NULL; ! 202: ! 203: if (i596_debug > 1) printk ("%s: init_rx_bufs %d.\n", dev->name, num); ! 204: ! 205: for (i = 0; i < num; i++) ! 206: { ! 207: if (!(rfd = (struct i596_rfd *)kmalloc(sizeof(struct i596_rfd), GFP_KERNEL))) ! 208: break; ! 209: ! 210: rfd->stat = 0x0000; ! 211: rfd->rbd = I596_NULL; ! 212: rfd->count = 0; ! 213: rfd->size = 1532; ! 214: if (i == 0) ! 215: { ! 216: rfd->cmd = CMD_EOL; ! 217: lp->rx_tail = rfd; ! 218: } ! 219: else ! 220: rfd->cmd = 0x0000; ! 221: ! 222: rfd->next = lp->scb.rfd; ! 223: lp->scb.rfd = rfd; ! 224: } ! 225: ! 226: if (i != 0) ! 227: lp->rx_tail->next = lp->scb.rfd; ! 228: ! 229: return (i); ! 230: } ! 231: ! 232: static inline void ! 233: remove_rx_bufs(struct device *dev) ! 234: { ! 235: struct i596_private *lp = (struct i596_private *)dev->priv; ! 236: struct i596_rfd *rfd = lp->scb.rfd; ! 237: ! 238: lp->rx_tail->next = (struct i596_rfd *)I596_NULL; ! 239: ! 240: do ! 241: { ! 242: lp->scb.rfd = rfd->next; ! 243: kfree_s(rfd, sizeof(struct i596_rfd)); ! 244: rfd = lp->scb.rfd; ! 245: } ! 246: while (rfd != lp->rx_tail); ! 247: } ! 248: ! 249: static inline void ! 250: init_i596_mem(struct device *dev) ! 251: { ! 252: struct i596_private *lp = (struct i596_private *)dev->priv; ! 253: short ioaddr = dev->base_addr; ! 254: int boguscnt = 100; ! 255: ! 256: /* change the scp address */ ! 257: outw(0, ioaddr); ! 258: outw(0, ioaddr); ! 259: outb(4, ioaddr+0xf); ! 260: outw(((((int)&lp->scp) & 0xffff) | 2), ioaddr); ! 261: outw((((int)&lp->scp)>>16) & 0xffff, ioaddr); ! 262: ! 263: lp->last_cmd = jiffies; ! 264: ! 265: lp->scp.sysbus = 0x00440000; ! 266: lp->scp.iscp = &(lp->iscp); ! 267: lp->iscp.scb = &(lp->scb); ! 268: lp->iscp.stat = 0x0001; ! 269: lp->cmd_backlog = 0; ! 270: ! 271: lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL; ! 272: ! 273: if (i596_debug > 2) printk("%s: starting i82596.\n", dev->name); ! 274: ! 275: (void) inb (ioaddr+0x10); ! 276: outb(4, ioaddr+0xf); ! 277: outw(0, ioaddr+4); ! 278: ! 279: while (lp->iscp.stat) ! 280: if (--boguscnt == 0) ! 281: { ! 282: printk("%s: i82596 initialization timed out with status %4.4x, cmd %4.4x.\n", ! 283: dev->name, lp->scb.status, lp->scb.command); ! 284: break; ! 285: } ! 286: ! 287: lp->scb.command = 0; ! 288: ! 289: memcpy (lp->i596_config, init_setup, 14); ! 290: lp->set_conf.command = CmdConfigure; ! 291: i596_add_cmd(dev, &lp->set_conf); ! 292: ! 293: memcpy (lp->eth_addr, dev->dev_addr, 6); ! 294: lp->set_add.command = CmdSASetup; ! 295: i596_add_cmd(dev, &lp->set_add); ! 296: ! 297: lp->tdr.command = CmdTDR; ! 298: i596_add_cmd(dev, &lp->tdr); ! 299: ! 300: boguscnt = 200; ! 301: while (lp->scb.status, lp->scb.command) ! 302: if (--boguscnt == 0) ! 303: { ! 304: printk("%s: receive unit start timed out with status %4.4x, cmd %4.4x.\n", ! 305: dev->name, lp->scb.status, lp->scb.command); ! 306: break; ! 307: } ! 308: ! 309: lp->scb.command = RX_START; ! 310: outw(0, ioaddr+4); ! 311: ! 312: boguscnt = 200; ! 313: while (lp->scb.status, lp->scb.command) ! 314: if (--boguscnt == 0) ! 315: { ! 316: printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n", ! 317: lp->scb.status, lp->scb.command); ! 318: break; ! 319: } ! 320: ! 321: return; ! 322: } ! 323: ! 324: static inline int ! 325: i596_rx(struct device *dev) ! 326: { ! 327: struct i596_private *lp = (struct i596_private *)dev->priv; ! 328: int frames = 0; ! 329: ! 330: if (i596_debug > 3) printk ("i596_rx()\n"); ! 331: ! 332: while ((lp->scb.rfd->stat) & STAT_C) ! 333: { ! 334: if (i596_debug >2) print_eth(lp->scb.rfd->data); ! 335: ! 336: if ((lp->scb.rfd->stat) & STAT_OK) ! 337: { ! 338: /* a good frame */ ! 339: int pkt_len = lp->scb.rfd->count & 0x3fff; ! 340: struct sk_buff *skb = dev_alloc_skb(pkt_len); ! 341: ! 342: frames++; ! 343: ! 344: if (skb == NULL) ! 345: { ! 346: printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); ! 347: lp->stats.rx_dropped++; ! 348: break; ! 349: } ! 350: ! 351: skb->dev = dev; ! 352: memcpy(skb_put(skb,pkt_len), lp->scb.rfd->data, pkt_len); ! 353: ! 354: skb->protocol=eth_type_trans(skb,dev); ! 355: netif_rx(skb); ! 356: lp->stats.rx_packets++; ! 357: ! 358: if (i596_debug > 4) print_eth(skb->data); ! 359: } ! 360: else ! 361: { ! 362: lp->stats.rx_errors++; ! 363: if ((lp->scb.rfd->stat) & 0x0001) lp->stats.collisions++; ! 364: if ((lp->scb.rfd->stat) & 0x0080) lp->stats.rx_length_errors++; ! 365: if ((lp->scb.rfd->stat) & 0x0100) lp->stats.rx_over_errors++; ! 366: if ((lp->scb.rfd->stat) & 0x0200) lp->stats.rx_fifo_errors++; ! 367: if ((lp->scb.rfd->stat) & 0x0400) lp->stats.rx_frame_errors++; ! 368: if ((lp->scb.rfd->stat) & 0x0800) lp->stats.rx_crc_errors++; ! 369: if ((lp->scb.rfd->stat) & 0x1000) lp->stats.rx_length_errors++; ! 370: } ! 371: ! 372: lp->scb.rfd->stat = 0; ! 373: lp->rx_tail->cmd = 0; ! 374: lp->rx_tail = lp->scb.rfd; ! 375: lp->scb.rfd = lp->scb.rfd->next; ! 376: lp->rx_tail->count = 0; ! 377: lp->rx_tail->cmd = CMD_EOL; ! 378: ! 379: } ! 380: ! 381: if (i596_debug > 3) printk ("frames %d\n", frames); ! 382: ! 383: return 0; ! 384: } ! 385: ! 386: static inline void ! 387: i596_cleanup_cmd(struct i596_private *lp) ! 388: { ! 389: struct i596_cmd *ptr; ! 390: int boguscnt = 100; ! 391: ! 392: if (i596_debug > 4) printk ("i596_cleanup_cmd\n"); ! 393: ! 394: while (lp->cmd_head != (struct i596_cmd *) I596_NULL) ! 395: { ! 396: ptr = lp->cmd_head; ! 397: ! 398: lp->cmd_head = lp->cmd_head->next; ! 399: lp->cmd_backlog--; ! 400: ! 401: switch ((ptr->command) & 0x7) ! 402: { ! 403: case CmdTx: ! 404: { ! 405: struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; ! 406: struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1; ! 407: ! 408: dev_kfree_skb(skb, FREE_WRITE); ! 409: ! 410: lp->stats.tx_errors++; ! 411: lp->stats.tx_aborted_errors++; ! 412: ! 413: ptr->next = (struct i596_cmd * ) I596_NULL; ! 414: kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); ! 415: break; ! 416: } ! 417: case CmdMulticastList: ! 418: { ! 419: unsigned short count = *((unsigned short *) (ptr + 1)); ! 420: ! 421: ptr->next = (struct i596_cmd * ) I596_NULL; ! 422: kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); ! 423: break; ! 424: } ! 425: default: ! 426: ptr->next = (struct i596_cmd * ) I596_NULL; ! 427: } ! 428: } ! 429: ! 430: while (lp->scb.status, lp->scb.command) ! 431: if (--boguscnt == 0) ! 432: { ! 433: printk("i596_cleanup_cmd timed out with status %4.4x, cmd %4.4x.\n", ! 434: lp->scb.status, lp->scb.command); ! 435: break; ! 436: } ! 437: ! 438: lp->scb.cmd = lp->cmd_head; ! 439: } ! 440: ! 441: static inline void ! 442: i596_reset(struct device *dev, struct i596_private *lp, int ioaddr) ! 443: { ! 444: int boguscnt = 100; ! 445: ! 446: if (i596_debug > 4) printk ("i596_reset\n"); ! 447: ! 448: while (lp->scb.status, lp->scb.command) ! 449: if (--boguscnt == 0) ! 450: { ! 451: printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n", ! 452: lp->scb.status, lp->scb.command); ! 453: break; ! 454: } ! 455: ! 456: dev->start = 0; ! 457: dev->tbusy = 1; ! 458: ! 459: lp->scb.command = CUC_ABORT|RX_ABORT; ! 460: outw(0, ioaddr+4); ! 461: ! 462: /* wait for shutdown */ ! 463: boguscnt = 400; ! 464: ! 465: while ((lp->scb.status, lp->scb.command) || lp->scb.command) ! 466: if (--boguscnt == 0) ! 467: { ! 468: printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n", ! 469: lp->scb.status, lp->scb.command); ! 470: break; ! 471: } ! 472: ! 473: i596_cleanup_cmd(lp); ! 474: i596_rx(dev); ! 475: ! 476: dev->start = 1; ! 477: dev->tbusy = 0; ! 478: dev->interrupt = 0; ! 479: init_i596_mem(dev); ! 480: } ! 481: ! 482: static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) ! 483: { ! 484: struct i596_private *lp = (struct i596_private *)dev->priv; ! 485: int ioaddr = dev->base_addr; ! 486: unsigned long flags; ! 487: int boguscnt = 100; ! 488: ! 489: if (i596_debug > 4) printk ("i596_add_cmd\n"); ! 490: ! 491: cmd->status = 0; ! 492: cmd->command |= (CMD_EOL|CMD_INTR); ! 493: cmd->next = (struct i596_cmd *) I596_NULL; ! 494: ! 495: save_flags(flags); ! 496: cli(); ! 497: if (lp->cmd_head != (struct i596_cmd *) I596_NULL) ! 498: lp->cmd_tail->next = cmd; ! 499: else ! 500: { ! 501: lp->cmd_head = cmd; ! 502: while (lp->scb.status, lp->scb.command) ! 503: if (--boguscnt == 0) ! 504: { ! 505: printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n", ! 506: lp->scb.status, lp->scb.command); ! 507: break; ! 508: } ! 509: ! 510: lp->scb.cmd = cmd; ! 511: lp->scb.command = CUC_START; ! 512: outw (0, ioaddr+4); ! 513: } ! 514: lp->cmd_tail = cmd; ! 515: lp->cmd_backlog++; ! 516: ! 517: lp->cmd_head = lp->scb.cmd; ! 518: restore_flags(flags); ! 519: ! 520: if (lp->cmd_backlog > 16) ! 521: { ! 522: int tickssofar = jiffies - lp->last_cmd; ! 523: ! 524: if (tickssofar < 25) return; ! 525: ! 526: printk("%s: command unit timed out, status resetting.\n", dev->name); ! 527: ! 528: i596_reset(dev, lp, ioaddr); ! 529: } ! 530: } ! 531: ! 532: static int ! 533: i596_open(struct device *dev) ! 534: { ! 535: int i; ! 536: ! 537: if (i596_debug > 1) ! 538: printk("%s: i596_open() irq %d.\n", dev->name, dev->irq); ! 539: ! 540: if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", NULL)) ! 541: return -EAGAIN; ! 542: ! 543: irq2dev_map[dev->irq] = dev; ! 544: ! 545: i = init_rx_bufs(dev, RX_RING_SIZE); ! 546: ! 547: if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) ! 548: printk("%s: only able to allocate %d receive buffers\n", dev->name, i); ! 549: ! 550: if (i < 4) ! 551: { ! 552: free_irq(dev->irq, NULL); ! 553: irq2dev_map[dev->irq] = 0; ! 554: return -EAGAIN; ! 555: } ! 556: ! 557: dev->tbusy = 0; ! 558: dev->interrupt = 0; ! 559: dev->start = 1; ! 560: MOD_INC_USE_COUNT; ! 561: ! 562: /* Initialize the 82596 memory */ ! 563: init_i596_mem(dev); ! 564: ! 565: return 0; /* Always succeed */ ! 566: } ! 567: ! 568: static int ! 569: i596_start_xmit(struct sk_buff *skb, struct device *dev) ! 570: { ! 571: struct i596_private *lp = (struct i596_private *)dev->priv; ! 572: int ioaddr = dev->base_addr; ! 573: struct tx_cmd *tx_cmd; ! 574: ! 575: if (i596_debug > 2) printk ("%s: Apricot start xmit\n", dev->name); ! 576: ! 577: /* Transmitter timeout, serious problems. */ ! 578: if (dev->tbusy) { ! 579: int tickssofar = jiffies - dev->trans_start; ! 580: if (tickssofar < 5) ! 581: return 1; ! 582: printk("%s: transmit timed out, status resetting.\n", ! 583: dev->name); ! 584: lp->stats.tx_errors++; ! 585: /* Try to restart the adaptor */ ! 586: if (lp->last_restart == lp->stats.tx_packets) { ! 587: if (i596_debug > 1) printk ("Resetting board.\n"); ! 588: ! 589: /* Shutdown and restart */ ! 590: i596_reset(dev,lp, ioaddr); ! 591: } else { ! 592: /* Issue a channel attention signal */ ! 593: if (i596_debug > 1) printk ("Kicking board.\n"); ! 594: ! 595: lp->scb.command = CUC_START|RX_START; ! 596: outw(0, ioaddr+4); ! 597: ! 598: lp->last_restart = lp->stats.tx_packets; ! 599: } ! 600: dev->tbusy = 0; ! 601: dev->trans_start = jiffies; ! 602: } ! 603: ! 604: /* If some higher level thinks we've misses a tx-done interrupt ! 605: we are passed NULL. n.b. dev_tint handles the cli()/sti() ! 606: itself. */ ! 607: if (skb == NULL) { ! 608: dev_tint(dev); ! 609: return 0; ! 610: } ! 611: ! 612: /* shouldn't happen */ ! 613: if (skb->len <= 0) return 0; ! 614: ! 615: if (i596_debug > 3) printk("%s: i596_start_xmit() called\n", dev->name); ! 616: ! 617: /* Block a timer-based transmit from overlapping. This could better be ! 618: done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ ! 619: if (set_bit(0, (void*)&dev->tbusy) != 0) ! 620: printk("%s: Transmitter access conflict.\n", dev->name); ! 621: else ! 622: { ! 623: short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; ! 624: dev->trans_start = jiffies; ! 625: ! 626: tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); ! 627: if (tx_cmd == NULL) ! 628: { ! 629: printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); ! 630: lp->stats.tx_dropped++; ! 631: ! 632: dev_kfree_skb(skb, FREE_WRITE); ! 633: } ! 634: else ! 635: { ! 636: tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1); ! 637: tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL; ! 638: ! 639: tx_cmd->cmd.command = CMD_FLEX|CmdTx; ! 640: ! 641: tx_cmd->pad = 0; ! 642: tx_cmd->size = 0; ! 643: tx_cmd->tbd->pad = 0; ! 644: tx_cmd->tbd->size = EOF | length; ! 645: ! 646: tx_cmd->tbd->data = skb->data; ! 647: ! 648: if (i596_debug > 3) print_eth(skb->data); ! 649: ! 650: i596_add_cmd(dev, (struct i596_cmd *)tx_cmd); ! 651: ! 652: lp->stats.tx_packets++; ! 653: } ! 654: } ! 655: ! 656: dev->tbusy = 0; ! 657: ! 658: return 0; ! 659: } ! 660: ! 661: ! 662: static void print_eth(char *add) ! 663: { ! 664: int i; ! 665: ! 666: printk ("Dest "); ! 667: for (i = 0; i < 6; i++) ! 668: printk(" %2.2X", (unsigned char)add[i]); ! 669: printk ("\n"); ! 670: ! 671: printk ("Source"); ! 672: for (i = 0; i < 6; i++) ! 673: printk(" %2.2X", (unsigned char)add[i+6]); ! 674: printk ("\n"); ! 675: printk ("type %2.2X%2.2X\n", (unsigned char)add[12], (unsigned char)add[13]); ! 676: } ! 677: ! 678: int apricot_probe(struct device *dev) ! 679: { ! 680: int i; ! 681: struct i596_private *lp; ! 682: int checksum = 0; ! 683: int ioaddr = 0x300; ! 684: char eth_addr[6]; ! 685: ! 686: /* this is easy the ethernet interface can only be at 0x300 */ ! 687: /* first check nothing is already registered here */ ! 688: ! 689: if (check_region(ioaddr, APRICOT_TOTAL_SIZE)) ! 690: return ENODEV; ! 691: ! 692: for (i = 0; i < 8; i++) ! 693: { ! 694: eth_addr[i] = inb(ioaddr+8+i); ! 695: checksum += eth_addr[i]; ! 696: } ! 697: ! 698: /* checksum is a multiple of 0x100, got this wrong first time ! 699: some machines have 0x100, some 0x200. The DOS driver doesn't ! 700: even bother with the checksum */ ! 701: ! 702: if (checksum % 0x100) return ENODEV; ! 703: ! 704: /* Some other boards trip the checksum.. but then appear as ether ! 705: address 0. Trap these - AC */ ! 706: ! 707: if(memcmp(eth_addr,"\x00\x00\x49",3)!= 0) ! 708: return ENODEV; ! 709: ! 710: request_region(ioaddr, APRICOT_TOTAL_SIZE, "apricot"); ! 711: ! 712: dev->base_addr = ioaddr; ! 713: ether_setup(dev); ! 714: printk("%s: Apricot 82596 at %#3x,", dev->name, ioaddr); ! 715: ! 716: for (i = 0; i < 6; i++) ! 717: printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]); ! 718: ! 719: dev->base_addr = ioaddr; ! 720: dev->irq = 10; ! 721: printk(" IRQ %d.\n", dev->irq); ! 722: ! 723: if (i596_debug > 0) printk(version); ! 724: ! 725: /* The APRICOT-specific entries in the device structure. */ ! 726: dev->open = &i596_open; ! 727: dev->stop = &i596_close; ! 728: dev->hard_start_xmit = &i596_start_xmit; ! 729: dev->get_stats = &i596_get_stats; ! 730: dev->set_multicast_list = &set_multicast_list; ! 731: ! 732: dev->mem_start = (int)kmalloc(sizeof(struct i596_private)+ 0x0f, GFP_KERNEL); ! 733: /* align for scp */ ! 734: dev->priv = (void *)((dev->mem_start + 0xf) & 0xfffffff0); ! 735: ! 736: lp = (struct i596_private *)dev->priv; ! 737: memset((void *)lp, 0, sizeof(struct i596_private)); ! 738: lp->scb.command = 0; ! 739: lp->scb.cmd = (struct i596_cmd *) I596_NULL; ! 740: lp->scb.rfd = (struct i596_rfd *)I596_NULL; ! 741: ! 742: return 0; ! 743: } ! 744: ! 745: static void ! 746: i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) ! 747: { ! 748: struct device *dev = (struct device *)(irq2dev_map[irq]); ! 749: struct i596_private *lp; ! 750: short ioaddr; ! 751: int boguscnt = 200; ! 752: unsigned short status, ack_cmd = 0; ! 753: ! 754: if (dev == NULL) { ! 755: printk ("i596_interrupt(): irq %d for unknown device.\n", irq); ! 756: return; ! 757: } ! 758: ! 759: if (i596_debug > 3) printk ("%s: i596_interrupt(): irq %d\n",dev->name, irq); ! 760: ! 761: if (dev->interrupt) ! 762: printk("%s: Re-entering the interrupt handler.\n", dev->name); ! 763: ! 764: dev->interrupt = 1; ! 765: ! 766: ioaddr = dev->base_addr; ! 767: ! 768: lp = (struct i596_private *)dev->priv; ! 769: ! 770: while (lp->scb.status, lp->scb.command) ! 771: if (--boguscnt == 0) ! 772: { ! 773: printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command); ! 774: break; ! 775: } ! 776: status = lp->scb.status; ! 777: ! 778: if (i596_debug > 4) ! 779: printk("%s: i596 interrupt, status %4.4x.\n", dev->name, status); ! 780: ! 781: ack_cmd = status & 0xf000; ! 782: ! 783: if ((status & 0x8000) || (status & 0x2000)) ! 784: { ! 785: struct i596_cmd *ptr; ! 786: ! 787: if ((i596_debug > 4) && (status & 0x8000)) ! 788: printk("%s: i596 interrupt completed command.\n", dev->name); ! 789: if ((i596_debug > 4) && (status & 0x2000)) ! 790: printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700); ! 791: ! 792: while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C)) ! 793: { ! 794: ptr = lp->cmd_head; ! 795: ! 796: lp->cmd_head = lp->cmd_head->next; ! 797: lp->cmd_backlog--; ! 798: ! 799: switch ((ptr->command) & 0x7) ! 800: { ! 801: case CmdTx: ! 802: { ! 803: struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; ! 804: struct sk_buff *skb = ((struct sk_buff *)(tx_cmd->tbd->data)) -1; ! 805: ! 806: dev_kfree_skb(skb, FREE_WRITE); ! 807: ! 808: if ((ptr->status) & STAT_OK) ! 809: { ! 810: if (i596_debug >2) print_eth(skb->data); ! 811: } ! 812: else ! 813: { ! 814: lp->stats.tx_errors++; ! 815: if ((ptr->status) & 0x0020) lp->stats.collisions++; ! 816: if (!((ptr->status) & 0x0040)) lp->stats.tx_heartbeat_errors++; ! 817: if ((ptr->status) & 0x0400) lp->stats.tx_carrier_errors++; ! 818: if ((ptr->status) & 0x0800) lp->stats.collisions++; ! 819: if ((ptr->status) & 0x1000) lp->stats.tx_aborted_errors++; ! 820: } ! 821: ! 822: ! 823: ptr->next = (struct i596_cmd * ) I596_NULL; ! 824: kfree_s((unsigned char *)tx_cmd, (sizeof (struct tx_cmd) + sizeof (struct i596_tbd))); ! 825: break; ! 826: } ! 827: case CmdMulticastList: ! 828: { ! 829: unsigned short count = *((unsigned short *) (ptr + 1)); ! 830: ! 831: ptr->next = (struct i596_cmd * ) I596_NULL; ! 832: kfree_s((unsigned char *)ptr, (sizeof (struct i596_cmd) + count + 2)); ! 833: break; ! 834: } ! 835: case CmdTDR: ! 836: { ! 837: unsigned long status = *((unsigned long *) (ptr + 1)); ! 838: ! 839: if (status & 0x8000) ! 840: { ! 841: if (i596_debug > 3) ! 842: printk("%s: link ok.\n", dev->name); ! 843: } ! 844: else ! 845: { ! 846: if (status & 0x4000) ! 847: printk("%s: Transceiver problem.\n", dev->name); ! 848: if (status & 0x2000) ! 849: printk("%s: Termination problem.\n", dev->name); ! 850: if (status & 0x1000) ! 851: printk("%s: Short circuit.\n", dev->name); ! 852: ! 853: printk("%s: Time %ld.\n", dev->name, status & 0x07ff); ! 854: } ! 855: } ! 856: default: ! 857: ptr->next = (struct i596_cmd * ) I596_NULL; ! 858: ! 859: lp->last_cmd = jiffies; ! 860: } ! 861: } ! 862: ! 863: ptr = lp->cmd_head; ! 864: while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail)) ! 865: { ! 866: ptr->command &= 0x1fff; ! 867: ptr = ptr->next; ! 868: } ! 869: ! 870: if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd |= CUC_START; ! 871: lp->scb.cmd = lp->cmd_head; ! 872: } ! 873: ! 874: if ((status & 0x1000) || (status & 0x4000)) ! 875: { ! 876: if ((i596_debug > 4) && (status & 0x4000)) ! 877: printk("%s: i596 interrupt received a frame.\n", dev->name); ! 878: if ((i596_debug > 4) && (status & 0x1000)) ! 879: printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x0070); ! 880: ! 881: i596_rx(dev); ! 882: ! 883: if (dev->start) ack_cmd |= RX_START; ! 884: } ! 885: ! 886: /* acknowledge the interrupt */ ! 887: ! 888: /* ! 889: if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start)) ack_cmd | = CUC_START; ! 890: */ ! 891: boguscnt = 100; ! 892: while (lp->scb.status, lp->scb.command) ! 893: if (--boguscnt == 0) ! 894: { ! 895: printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command); ! 896: break; ! 897: } ! 898: lp->scb.command = ack_cmd; ! 899: ! 900: (void) inb (ioaddr+0x10); ! 901: outb (4, ioaddr+0xf); ! 902: outw (0, ioaddr+4); ! 903: ! 904: if (i596_debug > 4) ! 905: printk("%s: exiting interrupt.\n", dev->name); ! 906: ! 907: dev->interrupt = 0; ! 908: return; ! 909: } ! 910: ! 911: static int ! 912: i596_close(struct device *dev) ! 913: { ! 914: int ioaddr = dev->base_addr; ! 915: struct i596_private *lp = (struct i596_private *)dev->priv; ! 916: int boguscnt = 200; ! 917: ! 918: dev->start = 0; ! 919: dev->tbusy = 1; ! 920: ! 921: if (i596_debug > 1) ! 922: printk("%s: Shutting down ethercard, status was %4.4x.\n", ! 923: dev->name, lp->scb.status); ! 924: ! 925: lp->scb.command = CUC_ABORT|RX_ABORT; ! 926: outw(0, ioaddr+4); ! 927: ! 928: i596_cleanup_cmd(lp); ! 929: ! 930: while (lp->scb.status, lp->scb.command) ! 931: if (--boguscnt == 0) ! 932: { ! 933: printk("%s: close timed out with status %4.4x, cmd %4.4x.\n", ! 934: dev->name, lp->scb.status, lp->scb.command); ! 935: break; ! 936: } ! 937: free_irq(dev->irq, NULL); ! 938: irq2dev_map[dev->irq] = 0; ! 939: remove_rx_bufs(dev); ! 940: MOD_DEC_USE_COUNT; ! 941: ! 942: return 0; ! 943: } ! 944: ! 945: static struct enet_statistics * ! 946: i596_get_stats(struct device *dev) ! 947: { ! 948: struct i596_private *lp = (struct i596_private *)dev->priv; ! 949: ! 950: return &lp->stats; ! 951: } ! 952: ! 953: /* ! 954: * Set or clear the multicast filter for this adaptor. ! 955: */ ! 956: ! 957: static void set_multicast_list(struct device *dev) ! 958: { ! 959: struct i596_private *lp = (struct i596_private *)dev->priv; ! 960: struct i596_cmd *cmd; ! 961: ! 962: if (i596_debug > 1) ! 963: printk ("%s: set multicast list %d\n", dev->name, dev->mc_count); ! 964: ! 965: if (dev->mc_count > 0) ! 966: { ! 967: struct dev_mc_list *dmi; ! 968: char *cp; ! 969: cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC); ! 970: if (cmd == NULL) ! 971: { ! 972: printk ("%s: set_multicast Memory squeeze.\n", dev->name); ! 973: return; ! 974: } ! 975: cmd->command = CmdMulticastList; ! 976: *((unsigned short *) (cmd + 1)) = dev->mc_count * 6; ! 977: cp=((char *)(cmd + 1))+2; ! 978: for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next) ! 979: { ! 980: memcpy(cp, dmi,6); ! 981: cp+=6; ! 982: } ! 983: print_eth (((char *)(cmd + 1)) + 2); ! 984: i596_add_cmd(dev, cmd); ! 985: } ! 986: else ! 987: { ! 988: if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) ! 989: return; ! 990: if (dev->mc_count == 0 && !(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) ! 991: { ! 992: if(dev->flags&IFF_ALLMULTI) ! 993: dev->flags|=IFF_PROMISC; ! 994: lp->i596_config[8] &= ~0x01; ! 995: } ! 996: else ! 997: lp->i596_config[8] |= 0x01; ! 998: ! 999: i596_add_cmd(dev, &lp->set_conf); ! 1000: } ! 1001: } ! 1002: ! 1003: #ifdef HAVE_DEVLIST ! 1004: static unsigned int apricot_portlist[] = {0x300, 0}; ! 1005: struct netdev_entry apricot_drv = ! 1006: {"apricot", apricot_probe, APRICOT_TOTAL_SIZE, apricot_portlist}; ! 1007: #endif ! 1008: ! 1009: #ifdef MODULE ! 1010: static char devicename[9] = { 0, }; ! 1011: static struct device dev_apricot = { ! 1012: devicename, /* device name inserted by /linux/drivers/net/net_init.c */ ! 1013: 0, 0, 0, 0, ! 1014: 0x300, 10, ! 1015: 0, 0, 0, NULL, apricot_probe }; ! 1016: ! 1017: static int io = 0x300; ! 1018: static int irq = 10; ! 1019: ! 1020: int ! 1021: init_module(void) ! 1022: { ! 1023: dev_apricot.base_addr = io; ! 1024: dev_apricot.irq = irq; ! 1025: if (register_netdev(&dev_apricot) != 0) ! 1026: return -EIO; ! 1027: return 0; ! 1028: } ! 1029: ! 1030: void ! 1031: cleanup_module(void) ! 1032: { ! 1033: unregister_netdev(&dev_apricot); ! 1034: kfree_s((void *)dev_apricot.mem_start, sizeof(struct i596_private) + 0xf); ! 1035: dev_apricot.priv = NULL; ! 1036: ! 1037: /* If we don't do this, we can't re-insmod it later. */ ! 1038: release_region(dev_apricot.base_addr, APRICOT_TOTAL_SIZE); ! 1039: } ! 1040: #endif /* MODULE */ ! 1041: ! 1042: /* ! 1043: * Local variables: ! 1044: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c apricot.c" ! 1045: * End: ! 1046: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.