|
|
1.1 ! root 1: /* smc-ultra.c: A SMC Ultra ethernet driver for linux. */ ! 2: /* ! 3: Written 1993,1994,1995 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: This is a driver for the SMC Ultra and SMC EtherEZ ethercards. ! 16: ! 17: This driver uses the cards in the 8390-compatible, shared memory mode. ! 18: Most of the run-time complexity is handled by the generic code in ! 19: 8390.c. The code in this file is responsible for ! 20: ! 21: ultra_probe() Detecting and initializing the card. ! 22: ultra_probe1() ! 23: ! 24: ultra_open() The card-specific details of starting, stopping ! 25: ultra_reset_8390() and resetting the 8390 NIC core. ! 26: ultra_close() ! 27: ! 28: ultra_block_input() Routines for reading and writing blocks of ! 29: ultra_block_output() packet buffer memory. ! 30: ! 31: This driver enables the shared memory only when doing the actual data ! 32: transfers to avoid a bug in early version of the card that corrupted ! 33: data transferred by a AHA1542. ! 34: ! 35: This driver does not support the programmed-I/O data transfer mode of ! 36: the EtherEZ. That support (if available) is smc-ez.c. Nor does it ! 37: use the non-8390-compatible "Altego" mode. (No support currently planned.) ! 38: ! 39: Changelog: ! 40: ! 41: Paul Gortmaker : multiple card support for module users. ! 42: */ ! 43: ! 44: static const char *version = ! 45: "smc-ultra.c:v1.12 1/18/95 Donald Becker ([email protected])\n"; ! 46: ! 47: ! 48: #include <linux/module.h> ! 49: ! 50: #include <linux/kernel.h> ! 51: #include <linux/sched.h> ! 52: #include <linux/errno.h> ! 53: #include <linux/string.h> ! 54: #include <asm/io.h> ! 55: #include <asm/system.h> ! 56: ! 57: #include <linux/netdevice.h> ! 58: #include <linux/etherdevice.h> ! 59: #include "8390.h" ! 60: ! 61: /* A zero-terminated list of I/O addresses to be probed. */ ! 62: static unsigned int ultra_portlist[] = ! 63: {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0}; ! 64: ! 65: int ultra_probe(struct device *dev); ! 66: int ultra_probe1(struct device *dev, int ioaddr); ! 67: ! 68: static int ultra_open(struct device *dev); ! 69: static void ultra_reset_8390(struct device *dev); ! 70: static void ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, ! 71: int ring_page); ! 72: static void ultra_block_input(struct device *dev, int count, ! 73: struct sk_buff *skb, int ring_offset); ! 74: static void ultra_block_output(struct device *dev, int count, ! 75: const unsigned char *buf, const start_page); ! 76: static int ultra_close_card(struct device *dev); ! 77: ! 78: ! 79: #define START_PG 0x00 /* First page of TX buffer */ ! 80: ! 81: #define ULTRA_CMDREG 0 /* Offset to ASIC command register. */ ! 82: #define ULTRA_RESET 0x80 /* Board reset, in ULTRA_CMDREG. */ ! 83: #define ULTRA_MEMENB 0x40 /* Enable the shared memory. */ ! 84: #define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */ ! 85: #define ULTRA_IO_EXTENT 32 ! 86: ! 87: /* Probe for the Ultra. This looks like a 8013 with the station ! 88: address PROM at I/O ports <base>+8 to <base>+13, with a checksum ! 89: following. ! 90: */ ! 91: #ifdef HAVE_DEVLIST ! 92: struct netdev_entry ultra_drv = ! 93: {"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist}; ! 94: #else ! 95: ! 96: int ultra_probe(struct device *dev) ! 97: { ! 98: int i; ! 99: int base_addr = dev ? dev->base_addr : 0; ! 100: ! 101: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 102: return ultra_probe1(dev, base_addr); ! 103: else if (base_addr != 0) /* Don't probe at all. */ ! 104: return ENXIO; ! 105: ! 106: for (i = 0; ultra_portlist[i]; i++) { ! 107: int ioaddr = ultra_portlist[i]; ! 108: if (check_region(ioaddr, ULTRA_IO_EXTENT)) ! 109: continue; ! 110: if (ultra_probe1(dev, ioaddr) == 0) ! 111: return 0; ! 112: } ! 113: ! 114: return ENODEV; ! 115: } ! 116: #endif ! 117: ! 118: int ultra_probe1(struct device *dev, int ioaddr) ! 119: { ! 120: int i; ! 121: int checksum = 0; ! 122: const char *model_name; ! 123: unsigned char eeprom_irq = 0; ! 124: static unsigned version_printed = 0; ! 125: /* Values from various config regs. */ ! 126: unsigned char num_pages, irqreg, addr; ! 127: unsigned char idreg = inb(ioaddr + 7); ! 128: unsigned char reg4 = inb(ioaddr + 4) & 0x7f; ! 129: ! 130: /* Check the ID nibble. */ ! 131: if ((idreg & 0xF0) != 0x20 /* SMC Ultra */ ! 132: && (idreg & 0xF0) != 0x40) /* SMC EtherEZ */ ! 133: return ENODEV; ! 134: ! 135: /* Select the station address register set. */ ! 136: outb(reg4, ioaddr + 4); ! 137: ! 138: for (i = 0; i < 8; i++) ! 139: checksum += inb(ioaddr + 8 + i); ! 140: if ((checksum & 0xff) != 0xFF) ! 141: return ENODEV; ! 142: ! 143: /* We should have a "dev" from Space.c or the static module table. */ ! 144: if (dev == NULL) { ! 145: printk("smc-ultra.c: Passed a NULL device.\n"); ! 146: dev = init_etherdev(0, 0); ! 147: } ! 148: ! 149: if (ei_debug && version_printed++ == 0) ! 150: printk(version); ! 151: ! 152: model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ"; ! 153: ! 154: printk("%s: %s at %#3x,", dev->name, model_name, ioaddr); ! 155: ! 156: for (i = 0; i < 6; i++) ! 157: printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); ! 158: ! 159: /* Switch from the station address to the alternate register set and ! 160: read the useful registers there. */ ! 161: outb(0x80 | reg4, ioaddr + 4); ! 162: ! 163: /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */ ! 164: outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c); ! 165: irqreg = inb(ioaddr + 0xd); ! 166: addr = inb(ioaddr + 0xb); ! 167: ! 168: /* Switch back to the station address register set so that the MS-DOS driver ! 169: can find the card after a warm boot. */ ! 170: outb(reg4, ioaddr + 4); ! 171: ! 172: if (dev->irq < 2) { ! 173: unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15}; ! 174: int irq; ! 175: ! 176: /* The IRQ bits are split. */ ! 177: irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)]; ! 178: ! 179: if (irq == 0) { ! 180: printk(", failed to detect IRQ line.\n"); ! 181: return -EAGAIN; ! 182: } ! 183: dev->irq = irq; ! 184: eeprom_irq = 1; ! 185: } ! 186: ! 187: /* Allocate dev->priv and fill in 8390 specific dev fields. */ ! 188: if (ethdev_init(dev)) { ! 189: printk (", no memory for dev->priv.\n"); ! 190: return -ENOMEM; ! 191: } ! 192: ! 193: /* OK, we are certain this is going to work. Setup the device. */ ! 194: request_region(ioaddr, ULTRA_IO_EXTENT, model_name); ! 195: ! 196: /* The 8390 isn't at the base address, so fake the offset */ ! 197: dev->base_addr = ioaddr+ULTRA_NIC_OFFSET; ! 198: ! 199: { ! 200: int addr_tbl[4] = {0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000}; ! 201: short num_pages_tbl[4] = {0x20, 0x40, 0x80, 0xff}; ! 202: ! 203: dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ; ! 204: num_pages = num_pages_tbl[(addr >> 4) & 3]; ! 205: } ! 206: ! 207: ei_status.name = model_name; ! 208: ei_status.word16 = 1; ! 209: ei_status.tx_start_page = START_PG; ! 210: ei_status.rx_start_page = START_PG + TX_PAGES; ! 211: ei_status.stop_page = num_pages; ! 212: ! 213: dev->rmem_start = dev->mem_start + TX_PAGES*256; ! 214: dev->mem_end = dev->rmem_end ! 215: = dev->mem_start + (ei_status.stop_page - START_PG)*256; ! 216: ! 217: printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ", ! 218: dev->irq, dev->mem_start, dev->mem_end-1); ! 219: ! 220: ei_status.reset_8390 = &ultra_reset_8390; ! 221: ei_status.block_input = &ultra_block_input; ! 222: ei_status.block_output = &ultra_block_output; ! 223: ei_status.get_8390_hdr = &ultra_get_8390_hdr; ! 224: dev->open = &ultra_open; ! 225: dev->stop = &ultra_close_card; ! 226: NS8390_init(dev, 0); ! 227: ! 228: return 0; ! 229: } ! 230: ! 231: static int ! 232: ultra_open(struct device *dev) ! 233: { ! 234: int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ ! 235: ! 236: if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name)) ! 237: return -EAGAIN; ! 238: ! 239: outb(ULTRA_MEMENB, ioaddr); /* Enable memory, 16 bit mode. */ ! 240: outb(0x80, ioaddr + 5); ! 241: outb(0x01, ioaddr + 6); /* Enable interrupts and memory. */ ! 242: ei_open(dev); ! 243: MOD_INC_USE_COUNT; ! 244: return 0; ! 245: } ! 246: ! 247: static void ! 248: ultra_reset_8390(struct device *dev) ! 249: { ! 250: int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */ ! 251: ! 252: outb(ULTRA_RESET, cmd_port); ! 253: if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies); ! 254: ei_status.txing = 0; ! 255: ! 256: outb(ULTRA_MEMENB, cmd_port); ! 257: ! 258: if (ei_debug > 1) printk("reset done\n"); ! 259: return; ! 260: } ! 261: ! 262: /* Grab the 8390 specific header. Similar to the block_input routine, but ! 263: we don't need to be concerned with ring wrap as the header will be at ! 264: the start of a page, so we optimize accordingly. */ ! 265: ! 266: static void ! 267: ultra_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) ! 268: { ! 269: ! 270: unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8); ! 271: ! 272: outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */ ! 273: #ifdef notdef ! 274: /* Officially this is what we are doing, but the readl() is faster */ ! 275: memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); ! 276: #else ! 277: ((unsigned int*)hdr)[0] = readl(hdr_start); ! 278: #endif ! 279: outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */ ! 280: } ! 281: ! 282: /* Block input and output are easy on shared memory ethercards, the only ! 283: complication is when the ring buffer wraps. */ ! 284: ! 285: static void ! 286: ultra_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) ! 287: { ! 288: unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8); ! 289: ! 290: /* Enable shared memory. */ ! 291: outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); ! 292: ! 293: if (xfer_start + count > dev->rmem_end) { ! 294: /* We must wrap the input move. */ ! 295: int semi_count = dev->rmem_end - xfer_start; ! 296: memcpy_fromio(skb->data, xfer_start, semi_count); ! 297: count -= semi_count; ! 298: memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); ! 299: } else { ! 300: /* Packet is in one chunk -- we can copy + cksum. */ ! 301: eth_io_copy_and_sum(skb, xfer_start, count, 0); ! 302: } ! 303: ! 304: outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */ ! 305: } ! 306: ! 307: static void ! 308: ultra_block_output(struct device *dev, int count, const unsigned char *buf, ! 309: int start_page) ! 310: { ! 311: unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8); ! 312: ! 313: /* Enable shared memory. */ ! 314: outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); ! 315: ! 316: memcpy_toio(shmem, buf, count); ! 317: ! 318: outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */ ! 319: } ! 320: ! 321: static int ! 322: ultra_close_card(struct device *dev) ! 323: { ! 324: int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */ ! 325: ! 326: dev->start = 0; ! 327: dev->tbusy = 1; ! 328: ! 329: if (ei_debug > 1) ! 330: printk("%s: Shutting down ethercard.\n", dev->name); ! 331: ! 332: outb(0x00, ioaddr + 6); /* Disable interrupts. */ ! 333: free_irq(dev->irq); ! 334: irq2dev_map[dev->irq] = 0; ! 335: ! 336: NS8390_init(dev, 0); ! 337: ! 338: /* We should someday disable shared memory and change to 8-bit mode ! 339: "just in case"... */ ! 340: ! 341: MOD_DEC_USE_COUNT; ! 342: ! 343: return 0; ! 344: } ! 345: ! 346: ! 347: #ifdef MODULE ! 348: #define MAX_ULTRA_CARDS 4 /* Max number of Ultra cards per module */ ! 349: #define NAMELEN 8 /* # of chars for storing dev->name */ ! 350: static char namelist[NAMELEN * MAX_ULTRA_CARDS] = { 0, }; ! 351: static struct device dev_ultra[MAX_ULTRA_CARDS] = { ! 352: { ! 353: NULL, /* assign a chunk of namelist[] below */ ! 354: 0, 0, 0, 0, ! 355: 0, 0, ! 356: 0, 0, 0, NULL, NULL ! 357: }, ! 358: }; ! 359: ! 360: static int io[MAX_ULTRA_CARDS] = { 0, }; ! 361: static int irq[MAX_ULTRA_CARDS] = { 0, }; ! 362: ! 363: /* This is set up so that only a single autoprobe takes place per call. ! 364: ISA device autoprobes on a running machine are not recommended. */ ! 365: int ! 366: init_module(void) ! 367: { ! 368: int this_dev, found = 0; ! 369: ! 370: for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { ! 371: struct device *dev = &dev_ultra[this_dev]; ! 372: dev->name = namelist+(NAMELEN*this_dev); ! 373: dev->irq = irq[this_dev]; ! 374: dev->base_addr = io[this_dev]; ! 375: dev->init = ultra_probe; ! 376: if (io[this_dev] == 0) { ! 377: if (this_dev != 0) break; /* only autoprobe 1st one */ ! 378: printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n"); ! 379: } ! 380: if (register_netdev(dev) != 0) { ! 381: printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); ! 382: if (found != 0) return 0; /* Got at least one. */ ! 383: return -ENXIO; ! 384: } ! 385: found++; ! 386: } ! 387: ! 388: return 0; ! 389: } ! 390: ! 391: void ! 392: cleanup_module(void) ! 393: { ! 394: int this_dev; ! 395: ! 396: for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { ! 397: struct device *dev = &dev_ultra[this_dev]; ! 398: if (dev->priv != NULL) { ! 399: /* NB: ultra_close_card() does free_irq + irq2dev */ ! 400: int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; ! 401: kfree(dev->priv); ! 402: dev->priv = NULL; ! 403: release_region(ioaddr, ULTRA_IO_EXTENT); ! 404: unregister_netdev(dev); ! 405: } ! 406: } ! 407: } ! 408: #endif /* MODULE */ ! 409: ! 410: ! 411: /* ! 412: * Local variables: ! 413: * compile-command: "gcc -D__KERNEL__ -Wall -O6 -I/usr/src/linux/net/inet -c smc-ultra.c" ! 414: * version-control: t ! 415: * kept-new-versions: 5 ! 416: * c-indent-level: 4 ! 417: * tab-width: 4 ! 418: * End: ! 419: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.