|
|
1.1 ! root 1: /* 3c59x.c: A 3Com 3c590/3c595 "Vortex" ethernet driver for linux. */ ! 2: /* ! 3: Written 1995 by Donald Becker. ! 4: ! 5: This software may be used and distributed according to the terms ! 6: of the GNU Public License, incorporated herein by reference. ! 7: ! 8: This driver is for the 3Com "Vortex" series ethercards. Members of ! 9: the series include the 3c590 PCI EtherLink III and 3c595-Tx PCI Fast ! 10: EtherLink. It also works with the 10Mbs-only 3c590 PCI EtherLink III. ! 11: ! 12: The author may be reached as [email protected], or C/O ! 13: Center of Excellence in Space Data and Information Sciences ! 14: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! 15: */ ! 16: ! 17: static char *version = "3c59x.c:v0.13 2/13/96 [email protected]\n"; ! 18: ! 19: /* "Knobs" that turn on special features. */ ! 20: /* Allow the use of bus master transfers instead of programmed-I/O for the ! 21: Tx process. Bus master transfers are always disabled by default, but ! 22: iff this is set they may be turned on using 'options'. */ ! 23: #define VORTEX_BUS_MASTER ! 24: ! 25: /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ ! 26: #define VORTEX_DEBUG 1 ! 27: ! 28: #include <linux/module.h> ! 29: ! 30: #include <linux/kernel.h> ! 31: #include <linux/sched.h> ! 32: #include <linux/string.h> ! 33: #include <linux/ptrace.h> ! 34: #include <linux/errno.h> ! 35: #include <linux/in.h> ! 36: #include <linux/ioport.h> ! 37: #include <linux/malloc.h> ! 38: #include <linux/interrupt.h> ! 39: #include <linux/pci.h> ! 40: #include <linux/bios32.h> ! 41: #include <linux/timer.h> ! 42: #include <asm/bitops.h> ! 43: #include <asm/io.h> ! 44: ! 45: #include <linux/netdevice.h> ! 46: #include <linux/etherdevice.h> ! 47: #include <linux/skbuff.h> ! 48: ! 49: #ifdef HAVE_SHARED_IRQ ! 50: #define USE_SHARED_IRQ ! 51: #include <linux/shared_irq.h> ! 52: #endif ! 53: ! 54: /* The total size is twice that of the original EtherLinkIII series: the ! 55: runtime register window, window 1, is now always mapped in. */ ! 56: #define VORTEX_TOTAL_SIZE 0x20 ! 57: ! 58: #ifdef HAVE_DEVLIST ! 59: struct netdev_entry tc59x_drv = ! 60: {"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL}; ! 61: #endif ! 62: ! 63: #ifdef VORTEX_DEBUG ! 64: int vortex_debug = VORTEX_DEBUG; ! 65: #else ! 66: int vortex_debug = 1; ! 67: #endif ! 68: ! 69: static int product_ids[] = {0x5900, 0x5950, 0x5951, 0x5952, 0, 0}; ! 70: static const char *product_names[] = { ! 71: "3c590 Vortex 10Mbps", ! 72: "3c595 Vortex 100baseTX", ! 73: "3c595 Vortex 100baseT4", ! 74: "3c595 Vortex 100base-MII", ! 75: "EISA Vortex 3c597", ! 76: }; ! 77: #define DEMON_INDEX 5 /* Caution! Must be consistent with above! */ ! 78: ! 79: /* ! 80: Theory of Operation ! 81: ! 82: I. Board Compatibility ! 83: ! 84: This device driver is designed for the 3Com FastEtherLink, 3Com's PCI to ! 85: 10/100baseT adapter. It also works with the 3c590, a similar product ! 86: with only a 10Mbs interface. ! 87: ! 88: II. Board-specific settings ! 89: ! 90: PCI bus devices are configured by the system at boot time, so no jumpers ! 91: need to be set on the board. The system BIOS should be set to assign the ! 92: PCI INTA signal to an otherwise unused system IRQ line. While it's ! 93: physically possible to shared PCI interrupt lines, the 1.2.0 kernel doesn't ! 94: support it. ! 95: ! 96: III. Driver operation ! 97: ! 98: The 3c59x series use an interface that's very similar to the previous 3c5x9 ! 99: series. The primary interface is two programmed-I/O FIFOs, with an ! 100: alternate single-contiguous-region bus-master transfer (see next). ! 101: ! 102: One extension that is advertised in a very large font is that the adapters ! 103: are capable of being bus masters. Unfortunately this capability is only for ! 104: a single contiguous region making it less useful than the list of transfer ! 105: regions available with the DEC Tulip or AMD PCnet. Given the significant ! 106: performance impact of taking an extra interrupt for each transfer, using ! 107: DMA transfers is a win only with large blocks. ! 108: ! 109: IIIC. Synchronization ! 110: The driver runs as two independent, single-threaded flows of control. One ! 111: is the send-packet routine, which enforces single-threaded use by the ! 112: dev->tbusy flag. The other thread is the interrupt handler, which is single ! 113: threaded by the hardware and other software. ! 114: ! 115: IV. Notes ! 116: ! 117: Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing both ! 118: 3c590 and 3c595 boards. ! 119: The name "Vortex" is the internal 3Com project name for the PCI ASIC, and ! 120: the not-yet-released (3/95) EISA version is called "Demon". According to ! 121: Terry these names come from rides at the local amusement park. ! 122: ! 123: The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes! ! 124: This driver only supports ethernet packets because of the skbuff allocation ! 125: limit of 4K. ! 126: */ ! 127: ! 128: #define TCOM_VENDOR_ID 0x10B7 /* 3Com's manufacturer's ID. */ ! 129: ! 130: /* Operational defintions. ! 131: These are not used by other compilation units and thus are not ! 132: exported in a ".h" file. ! 133: ! 134: First the windows. There are eight register windows, with the command ! 135: and status registers available in each. ! 136: */ ! 137: #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) ! 138: #define EL3_CMD 0x0e ! 139: #define EL3_STATUS 0x0e ! 140: ! 141: /* The top five bits written to EL3_CMD are a command, the lower ! 142: 11 bits are the parameter, if applicable. ! 143: Note that 11 parameters bits was fine for ethernet, but the new chip ! 144: can handle FDDI lenght frames (~4500 octets) and now parameters count ! 145: 32-bit 'Dwords' rather than octets. */ ! 146: ! 147: enum vortex_cmd { ! 148: TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, ! 149: RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, ! 150: TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, ! 151: FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, ! 152: SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, ! 153: SetTxThreshold = 18<<11, SetTxStart = 19<<11, ! 154: StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, ! 155: StatsDisable = 22<<11, StopCoax = 23<<11,}; ! 156: ! 157: /* The SetRxFilter command accepts the following classes: */ ! 158: enum RxFilter { ! 159: RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; ! 160: ! 161: /* Bits in the general status register. */ ! 162: enum vortex_status { ! 163: IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, ! 164: TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, ! 165: IntReq = 0x0040, StatsFull = 0x0080, DMADone = 1<<8, ! 166: DMAInProgress = 1<<11, /* DMA controller is still busy.*/ ! 167: CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ ! 168: }; ! 169: ! 170: /* Register window 1 offsets, the window used in normal operation. ! 171: On the Vortex this window is always mapped at offsets 0x10-0x1f. */ ! 172: enum Window1 { ! 173: TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, ! 174: RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, ! 175: TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ ! 176: }; ! 177: enum Window0 { ! 178: Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ ! 179: }; ! 180: enum Win0_EEPROM_bits { ! 181: EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, ! 182: EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ ! 183: EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ ! 184: }; ! 185: /* EEPROM locations. */ ! 186: enum eeprom_offset { ! 187: PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, ! 188: EtherLink3ID=7, IFXcvrIO=8, IRQLine=9, ! 189: NodeAddr01=10, NodeAddr23=11, NodeAddr45=12, ! 190: DriverTune=13, Checksum=15}; ! 191: ! 192: enum Window3 { /* Window 3: MAC/config bits. */ ! 193: Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, ! 194: }; ! 195: union wn3_config { ! 196: int i; ! 197: struct w3_config_fields { ! 198: unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; ! 199: int pad8:8; ! 200: unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1; ! 201: int pad24:8; ! 202: } u; ! 203: }; ! 204: ! 205: enum Window4 { ! 206: Wn4_Media = 0x0A, /* Window 4: Various transcvr/media bits. */ ! 207: }; ! 208: enum Win4_Media_bits { ! 209: Media_TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ ! 210: }; ! 211: enum Window7 { /* Window 7: Bus Master control. */ ! 212: Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, ! 213: }; ! 214: ! 215: struct vortex_private { ! 216: char devname[8]; /* "ethN" string, also for kernel debug. */ ! 217: const char *product_name; ! 218: struct device *next_module; ! 219: struct enet_statistics stats; ! 220: #ifdef VORTEX_BUS_MASTER ! 221: struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ ! 222: #endif ! 223: struct timer_list timer; /* Media selection timer. */ ! 224: int options; /* User-settable driver options (none yet). */ ! 225: unsigned int media_override:3, full_duplex:1, bus_master:1, autoselect:1; ! 226: }; ! 227: ! 228: static char *if_names[] = { ! 229: "10baseT", "10Mbs AUI", "undefined", "10base2", ! 230: "100baseTX", "100baseFX", "MII", "undefined"}; ! 231: ! 232: static int vortex_scan(struct device *dev); ! 233: static int vortex_found_device(struct device *dev, int ioaddr, int irq, ! 234: int product_index, int options); ! 235: static int vortex_probe1(struct device *dev); ! 236: static int vortex_open(struct device *dev); ! 237: static void vortex_timer(unsigned long arg); ! 238: static int vortex_start_xmit(struct sk_buff *skb, struct device *dev); ! 239: static int vortex_rx(struct device *dev); ! 240: static void vortex_interrupt(int irq, struct pt_regs *regs); ! 241: static int vortex_close(struct device *dev); ! 242: static void update_stats(int addr, struct device *dev); ! 243: static struct enet_statistics *vortex_get_stats(struct device *dev); ! 244: static void set_multicast_list(struct device *dev); ! 245: ! 246: ! 247: /* Unlike the other PCI cards the 59x cards don't need a large contiguous ! 248: memory region, so making the driver a loadable module is feasible. ! 249: ! 250: Unfortuneately maximizing the shared code between the integrated and ! 251: module version of the driver results in a complicated set of initialization ! 252: procedures. ! 253: init_module() -- modules / tc59x_init() -- built-in ! 254: The wrappers for vortex_scan() ! 255: vortex_scan() The common routine that scans for PCI and EISA cards ! 256: vortex_found_device() Allocate a device structure when we find a card. ! 257: Different versions exist for modules and built-in. ! 258: vortex_probe1() Fill in the device structure -- this is seperated ! 259: so that the modules code can put it in dev->init. ! 260: */ ! 261: /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ ! 262: /* Note: this is the only limit on the number of cards supported!! */ ! 263: int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,}; ! 264: ! 265: #ifdef MODULE ! 266: static int debug = -1; ! 267: /* A list of all installed Vortex devices, for removing the driver module. */ ! 268: static struct device *root_vortex_dev = NULL; ! 269: ! 270: int ! 271: init_module(void) ! 272: { ! 273: int cards_found; ! 274: ! 275: if (debug >= 0) ! 276: vortex_debug = debug; ! 277: if (vortex_debug) ! 278: printk(version); ! 279: ! 280: root_vortex_dev = NULL; ! 281: cards_found = vortex_scan(0); ! 282: return cards_found < 0 ? cards_found : 0; ! 283: } ! 284: ! 285: #else ! 286: unsigned long tc59x_probe(struct device *dev) ! 287: { ! 288: int cards_found = 0; ! 289: ! 290: cards_found = vortex_scan(dev); ! 291: ! 292: if (vortex_debug > 0 && cards_found) ! 293: printk(version); ! 294: ! 295: return cards_found ? 0 : -ENODEV; ! 296: } ! 297: #endif /* not MODULE */ ! 298: ! 299: static int vortex_scan(struct device *dev) ! 300: { ! 301: int cards_found = 0; ! 302: ! 303: if (pcibios_present()) { ! 304: static int pci_index = 0; ! 305: for (; pci_index < 8; pci_index++) { ! 306: unsigned char pci_bus, pci_device_fn, pci_irq_line, pci_latency; ! 307: unsigned int pci_ioaddr; ! 308: unsigned short pci_command; ! 309: int index; ! 310: ! 311: for (index = 0; product_ids[index]; index++) { ! 312: if ( ! pcibios_find_device(TCOM_VENDOR_ID, product_ids[index], ! 313: pci_index, &pci_bus, ! 314: &pci_device_fn)) ! 315: break; ! 316: } ! 317: if ( ! product_ids[index]) ! 318: break; ! 319: ! 320: pcibios_read_config_byte(pci_bus, pci_device_fn, ! 321: PCI_INTERRUPT_LINE, &pci_irq_line); ! 322: pcibios_read_config_dword(pci_bus, pci_device_fn, ! 323: PCI_BASE_ADDRESS_0, &pci_ioaddr); ! 324: /* Remove I/O space marker in bit 0. */ ! 325: pci_ioaddr &= ~3; ! 326: ! 327: #ifdef VORTEX_BUS_MASTER ! 328: /* Get and check the bus-master and latency values. ! 329: Some PCI BIOSes fail to set the master-enable bit, and ! 330: the latency timer must be set to the maximum value to avoid ! 331: data corruption that occurs when the timer expires during ! 332: a transfer. Yes, it's a bug. */ ! 333: pcibios_read_config_word(pci_bus, pci_device_fn, ! 334: PCI_COMMAND, &pci_command); ! 335: if ( ! (pci_command & PCI_COMMAND_MASTER)) { ! 336: printk(" PCI Master Bit has not been set! Setting...\n"); ! 337: pci_command |= PCI_COMMAND_MASTER; ! 338: pcibios_write_config_word(pci_bus, pci_device_fn, ! 339: PCI_COMMAND, pci_command); ! 340: } ! 341: pcibios_read_config_byte(pci_bus, pci_device_fn, ! 342: PCI_LATENCY_TIMER, &pci_latency); ! 343: if (pci_latency != 255) { ! 344: printk(" Overriding PCI latency timer (CFLT) setting of %d, new value is 255.\n", pci_latency); ! 345: pcibios_write_config_byte(pci_bus, pci_device_fn, ! 346: PCI_LATENCY_TIMER, 255); ! 347: } ! 348: #endif /* VORTEX_BUS_MASTER */ ! 349: vortex_found_device(dev, pci_ioaddr, pci_irq_line, index, ! 350: dev && dev->mem_start ? dev->mem_start ! 351: : options[cards_found]); ! 352: dev = 0; ! 353: cards_found++; ! 354: } ! 355: } ! 356: ! 357: /* Now check all slots of the EISA bus. */ ! 358: if (EISA_bus) { ! 359: static int ioaddr = 0x1000; ! 360: for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { ! 361: /* Check the standard EISA ID register for an encoded '3Com'. */ ! 362: if (inw(ioaddr + 0xC80) != 0x6d50) ! 363: continue; ! 364: /* Check for a product that we support. */ ! 365: if ((inw(ioaddr + 0xC82) & 0xFFF0) != 0x5970 ! 366: && (inw(ioaddr + 0xC82) & 0xFFF0) != 0x5920) ! 367: continue; ! 368: vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12, ! 369: DEMON_INDEX, dev && dev->mem_start ! 370: ? dev->mem_start : options[cards_found]); ! 371: dev = 0; ! 372: cards_found++; ! 373: } ! 374: } ! 375: ! 376: return cards_found; ! 377: } ! 378: ! 379: static int vortex_found_device(struct device *dev, int ioaddr, int irq, ! 380: int product_index, int options) ! 381: { ! 382: struct vortex_private *vp; ! 383: ! 384: #ifdef MODULE ! 385: /* Allocate and fill new device structure. */ ! 386: int dev_size = sizeof(struct device) + ! 387: sizeof(struct vortex_private); ! 388: ! 389: dev = (struct device *) kmalloc(dev_size, GFP_KERNEL); ! 390: memset(dev, 0, dev_size); ! 391: dev->priv = ((void *)dev) + sizeof(struct device); ! 392: vp = (struct vortex_private *)dev->priv; ! 393: dev->name = vp->devname; /* An empty string. */ ! 394: dev->base_addr = ioaddr; ! 395: dev->irq = irq; ! 396: dev->init = vortex_probe1; ! 397: vp->product_name = product_names[product_index]; ! 398: vp->options = options; ! 399: if (options >= 0) { ! 400: vp->media_override = ((options & 7) == 2) ? 0 : options & 7; ! 401: vp->full_duplex = (options & 8) ? 1 : 0; ! 402: vp->bus_master = (options & 16) ? 1 : 0; ! 403: } else { ! 404: vp->media_override = 7; ! 405: vp->full_duplex = 0; ! 406: vp->bus_master = 0; ! 407: } ! 408: ether_setup(dev); ! 409: vp->next_module = root_vortex_dev; ! 410: root_vortex_dev = dev; ! 411: if (register_netdev(dev) != 0) ! 412: return -EIO; ! 413: #else /* not a MODULE */ ! 414: if (dev) { ! 415: dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL); ! 416: memset(dev->priv, 0, sizeof (struct vortex_private)); ! 417: } ! 418: dev = init_etherdev(dev, sizeof(struct vortex_private)); ! 419: dev->base_addr = ioaddr; ! 420: dev->irq = irq; ! 421: vp = (struct vortex_private *)dev->priv; ! 422: vp->product_name = product_names[product_index]; ! 423: vp->options = options; ! 424: if (options >= 0) { ! 425: vp->media_override = ((options & 7) == 2) ? 0 : options & 7; ! 426: vp->full_duplex = (options & 8) ? 1 : 0; ! 427: vp->bus_master = (options & 16) ? 1 : 0; ! 428: } else { ! 429: vp->media_override = 7; ! 430: vp->full_duplex = 0; ! 431: vp->bus_master = 0; ! 432: } ! 433: ! 434: vortex_probe1(dev); ! 435: #endif /* MODULE */ ! 436: return 0; ! 437: } ! 438: ! 439: static int vortex_probe1(struct device *dev) ! 440: { ! 441: int ioaddr = dev->base_addr; ! 442: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 443: int i; ! 444: ! 445: printk("%s: 3Com %s at %#3x,", dev->name, ! 446: vp->product_name, ioaddr); ! 447: ! 448: /* Read the station address from the EEPROM. */ ! 449: EL3WINDOW(0); ! 450: for (i = 0; i < 3; i++) { ! 451: short *phys_addr = (short *)dev->dev_addr; ! 452: int timer; ! 453: outw(EEPROM_Read + PhysAddr01 + i, ioaddr + Wn0EepromCmd); ! 454: /* Pause for at least 162 us. for the read to take place. */ ! 455: for (timer = 0; timer < 162*4 + 400; timer++) { ! 456: SLOW_DOWN_IO; ! 457: if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) ! 458: break; ! 459: } ! 460: phys_addr[i] = htons(inw(ioaddr + 12)); ! 461: } ! 462: for (i = 0; i < 6; i++) ! 463: printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); ! 464: printk(", IRQ %d\n", dev->irq); ! 465: /* Tell them about an invalid IRQ. */ ! 466: if (vortex_debug && (dev->irq <= 0 || dev->irq > 15)) ! 467: printk(" *** Warning: this IRQ is unlikely to work!\n"); ! 468: ! 469: { ! 470: char *ram_split[] = {"5:3", "3:1", "1:1", "invalid"}; ! 471: union wn3_config config; ! 472: EL3WINDOW(3); ! 473: config.i = inl(ioaddr + Wn3_Config); ! 474: if (vortex_debug > 1) ! 475: printk(" Internal config register is %4.4x, transceivers %#x.\n", ! 476: config.i, inw(ioaddr + Wn3_Options)); ! 477: printk(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", ! 478: 8 << config.u.ram_size, ! 479: config.u.ram_width ? "word" : "byte", ! 480: ram_split[config.u.ram_split], ! 481: config.u.autoselect ? "autoselect/" : "", ! 482: if_names[config.u.xcvr]); ! 483: dev->if_port = config.u.xcvr; ! 484: vp->autoselect = config.u.autoselect; ! 485: } ! 486: ! 487: /* We do a request_region() only to register /proc/ioports info. */ ! 488: request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name); ! 489: ! 490: /* The 3c59x-specific entries in the device structure. */ ! 491: dev->open = &vortex_open; ! 492: dev->hard_start_xmit = &vortex_start_xmit; ! 493: dev->stop = &vortex_close; ! 494: dev->get_stats = &vortex_get_stats; ! 495: dev->set_multicast_list = &set_multicast_list; ! 496: #if defined (HAVE_SET_MAC_ADDR) && 0 ! 497: dev->set_mac_address = &set_mac_address; ! 498: #endif ! 499: ! 500: return 0; ! 501: } ! 502: ! 503: ! 504: static int ! 505: vortex_open(struct device *dev) ! 506: { ! 507: int ioaddr = dev->base_addr; ! 508: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 509: union wn3_config config; ! 510: int i; ! 511: ! 512: /* Before initializing select the active media port. */ ! 513: EL3WINDOW(3); ! 514: if (vp->full_duplex) ! 515: outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ ! 516: config.i = inl(ioaddr + Wn3_Config); ! 517: ! 518: if (vp->media_override != 7) { ! 519: if (vortex_debug > 1) ! 520: printk("%s: Media override to transceiver %d (%s).\n", ! 521: dev->name, vp->media_override, if_names[vp->media_override]); ! 522: config.u.xcvr = vp->media_override; ! 523: dev->if_port = vp->media_override; ! 524: outl(config.i, ioaddr + Wn3_Config); ! 525: } ! 526: ! 527: if (vortex_debug > 1) { ! 528: printk("%s: vortex_open() InternalConfig %8.8x.\n", ! 529: dev->name, config.i); ! 530: } ! 531: ! 532: outw(TxReset, ioaddr + EL3_CMD); ! 533: for (i = 20; i >= 0 ; i--) ! 534: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 535: break; ! 536: ! 537: outw(RxReset, ioaddr + EL3_CMD); ! 538: /* Wait a few ticks for the RxReset command to complete. */ ! 539: for (i = 20; i >= 0 ; i--) ! 540: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 541: break; ! 542: ! 543: outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); ! 544: ! 545: #ifdef USE_SHARED_IRQ ! 546: i = request_shared_irq(dev->irq, &vortex_interrupt, dev, vp->product_name); ! 547: if (i) /* Error */ ! 548: return i; ! 549: #else ! 550: if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL) ! 551: return -EAGAIN; ! 552: irq2dev_map[dev->irq] = dev; ! 553: if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) { ! 554: irq2dev_map[dev->irq] = NULL; ! 555: return -EAGAIN; ! 556: } ! 557: #endif ! 558: ! 559: if (vortex_debug > 1) { ! 560: EL3WINDOW(4); ! 561: printk("%s: vortex_open() irq %d media status %4.4x.\n", ! 562: dev->name, dev->irq, inw(ioaddr + Wn4_Media)); ! 563: } ! 564: ! 565: /* Set the station address and mask in window 2 each time opened. */ ! 566: EL3WINDOW(2); ! 567: for (i = 0; i < 6; i++) ! 568: outb(dev->dev_addr[i], ioaddr + i); ! 569: for (; i < 12; i+=2) ! 570: outw(0, ioaddr + i); ! 571: ! 572: if (dev->if_port == 3) ! 573: /* Start the thinnet transceiver. We should really wait 50ms...*/ ! 574: outw(StartCoax, ioaddr + EL3_CMD); ! 575: else if (dev->if_port == 0) { ! 576: /* 10baseT interface, enabled link beat and jabber check. */ ! 577: EL3WINDOW(4); ! 578: outw(inw(ioaddr + Wn4_Media) | Media_TP, ioaddr + Wn4_Media); ! 579: } ! 580: ! 581: /* Switch to the stats window, and clear all stats by reading. */ ! 582: outw(StatsDisable, ioaddr + EL3_CMD); ! 583: EL3WINDOW(6); ! 584: for (i = 0; i < 10; i++) ! 585: inb(ioaddr + i); ! 586: inw(ioaddr + 10); ! 587: inw(ioaddr + 12); ! 588: /* New: On the Vortex we must also clear the BadSSD counter. */ ! 589: EL3WINDOW(4); ! 590: inb(ioaddr + 12); ! 591: ! 592: /* Switch to register set 7 for normal use. */ ! 593: EL3WINDOW(7); ! 594: ! 595: /* Accept b-case and phys addr only. */ ! 596: outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); ! 597: outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ ! 598: ! 599: dev->tbusy = 0; ! 600: dev->interrupt = 0; ! 601: dev->start = 1; ! 602: ! 603: outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ ! 604: outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ ! 605: /* Allow status bits to be seen. */ ! 606: outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); ! 607: /* Ack all pending events, and set active indicator mask. */ ! 608: outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, ! 609: ioaddr + EL3_CMD); ! 610: outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull ! 611: | DMADone, ioaddr + EL3_CMD); ! 612: ! 613: #ifdef MODULE ! 614: MOD_INC_USE_COUNT; ! 615: #endif ! 616: ! 617: if (vp->autoselect) { ! 618: init_timer(&vp->timer); ! 619: vp->timer.expires = (14*HZ)/10; /* 1.4 sec. */ ! 620: vp->timer.data = (unsigned long)dev; ! 621: vp->timer.function = &vortex_timer; /* timer handler */ ! 622: add_timer(&vp->timer); ! 623: } ! 624: return 0; ! 625: } ! 626: ! 627: static void vortex_timer(unsigned long data) ! 628: { ! 629: struct device *dev = (struct device *)data; ! 630: if (vortex_debug > 2) ! 631: printk("%s: Media selection timer tick happened.\n", dev->name); ! 632: /* ToDo: active media selection here! */ ! 633: } ! 634: ! 635: static int ! 636: vortex_start_xmit(struct sk_buff *skb, struct device *dev) ! 637: { ! 638: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 639: int ioaddr = dev->base_addr; ! 640: ! 641: /* Transmitter timeout, serious problems. */ ! 642: if (dev->tbusy) { ! 643: int tickssofar = jiffies - dev->trans_start; ! 644: if (tickssofar < 40) ! 645: return 1; ! 646: printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", ! 647: dev->name, inb(ioaddr + TxStatus), inw(ioaddr + EL3_STATUS)); ! 648: vp->stats.tx_errors++; ! 649: /* Issue TX_RESET and TX_START commands. */ ! 650: outw(TxReset, ioaddr + EL3_CMD); ! 651: { ! 652: int i; ! 653: for (i = 20; i >= 0 ; i--) ! 654: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 655: break; ! 656: } ! 657: outw(TxEnable, ioaddr + EL3_CMD); ! 658: dev->trans_start = jiffies; ! 659: dev->tbusy = 0; ! 660: return 0; ! 661: } ! 662: ! 663: if (skb == NULL || skb->len <= 0) { ! 664: printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", ! 665: dev->name); ! 666: dev_tint(dev); ! 667: return 0; ! 668: } ! 669: ! 670: /* Block a timer-based transmit from overlapping. This could better be ! 671: done with atomic_swap(1, dev->tbusy), but set_bit() works as well. ! 672: If this ever occurs the queue layer is doing something evil! */ ! 673: if (set_bit(0, (void*)&dev->tbusy) != 0) { ! 674: printk("%s: Transmitter access conflict.\n", dev->name); ! 675: return 1; ! 676: } ! 677: ! 678: /* Put out the doubleword header... */ ! 679: outl(skb->len, ioaddr + TX_FIFO); ! 680: #ifdef VORTEX_BUS_MASTER ! 681: if (vp->bus_master) { ! 682: /* Set the bus-master controller to transfer the packet. */ ! 683: outl((int)(skb->data), ioaddr + Wn7_MasterAddr); ! 684: outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); ! 685: vp->tx_skb = skb; ! 686: outw(StartDMADown, ioaddr + EL3_CMD); ! 687: } else { ! 688: /* ... and the packet rounded to a doubleword. */ ! 689: outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); ! 690: dev_kfree_skb (skb, FREE_WRITE); ! 691: if (inw(ioaddr + TxFree) > 1536) { ! 692: dev->tbusy = 0; ! 693: } else ! 694: /* Interrupt us when the FIFO has room for max-sized packet. */ ! 695: outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); ! 696: } ! 697: #else ! 698: /* ... and the packet rounded to a doubleword. */ ! 699: outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); ! 700: dev_kfree_skb (skb, FREE_WRITE); ! 701: if (inw(ioaddr + TxFree) > 1536) { ! 702: dev->tbusy = 0; ! 703: } else ! 704: /* Interrupt us when the FIFO has room for max-sized packet. */ ! 705: outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); ! 706: #endif /* bus master */ ! 707: ! 708: dev->trans_start = jiffies; ! 709: ! 710: /* Clear the Tx status stack. */ ! 711: { ! 712: short tx_status; ! 713: int i = 4; ! 714: ! 715: while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { ! 716: if (tx_status & 0x3C) { /* A Tx-disabling error occured. */ ! 717: if (vortex_debug > 2) ! 718: printk("%s: Tx error, status %2.2x.\n", ! 719: dev->name, tx_status); ! 720: if (tx_status & 0x04) vp->stats.tx_fifo_errors++; ! 721: if (tx_status & 0x38) vp->stats.tx_aborted_errors++; ! 722: if (tx_status & 0x30) { ! 723: int j; ! 724: outw(TxReset, ioaddr + EL3_CMD); ! 725: for (j = 20; j >= 0 ; j--) ! 726: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 727: break; ! 728: } ! 729: outw(TxEnable, ioaddr + EL3_CMD); ! 730: } ! 731: outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ ! 732: } ! 733: } ! 734: return 0; ! 735: } ! 736: ! 737: /* The interrupt handler does all of the Rx thread work and cleans up ! 738: after the Tx thread. */ ! 739: static void vortex_interrupt(int irq, struct pt_regs *regs) ! 740: { ! 741: #ifdef USE_SHARED_IRQ ! 742: struct device *dev = (struct device *)(irq == 0 ? regs : irq2dev_map[irq]); ! 743: #else ! 744: struct device *dev = (struct device *)(irq2dev_map[irq]); ! 745: #endif ! 746: struct vortex_private *lp; ! 747: int ioaddr, status; ! 748: int latency; ! 749: int i = 0; ! 750: ! 751: if (dev == NULL) { ! 752: printk ("vortex_interrupt(): irq %d for unknown device.\n", irq); ! 753: return; ! 754: } ! 755: ! 756: if (dev->interrupt) ! 757: printk("%s: Re-entering the interrupt handler.\n", dev->name); ! 758: dev->interrupt = 1; ! 759: ! 760: ioaddr = dev->base_addr; ! 761: latency = inb(ioaddr + Timer); ! 762: lp = (struct vortex_private *)dev->priv; ! 763: ! 764: status = inw(ioaddr + EL3_STATUS); ! 765: ! 766: if (vortex_debug > 4) ! 767: printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name, ! 768: status, latency); ! 769: if ((status & 0xE000) != 0xE000) { ! 770: static int donedidthis=0; ! 771: /* Some interrupt controllers store a bogus interrupt from boot-time. ! 772: Ignore a single early interrupt, but don't hang the machine for ! 773: other interrupt problems. */ ! 774: if (donedidthis++ > 1) { ! 775: printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", ! 776: dev->name, status, dev->start); ! 777: free_irq(dev->irq); ! 778: } ! 779: } ! 780: ! 781: do { ! 782: if (vortex_debug > 5) ! 783: printk("%s: In interrupt loop, status %4.4x.\n", ! 784: dev->name, status); ! 785: if (status & RxComplete) ! 786: vortex_rx(dev); ! 787: ! 788: if (status & TxAvailable) { ! 789: if (vortex_debug > 5) ! 790: printk(" TX room bit was handled.\n"); ! 791: /* There's room in the FIFO for a full-sized packet. */ ! 792: outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); ! 793: dev->tbusy = 0; ! 794: mark_bh(NET_BH); ! 795: } ! 796: #ifdef VORTEX_BUS_MASTER ! 797: if (status & DMADone) { ! 798: outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ ! 799: dev->tbusy = 0; ! 800: mark_bh(NET_BH); ! 801: } ! 802: #endif ! 803: if (status & (AdapterFailure | RxEarly | StatsFull)) { ! 804: /* Handle all uncommon interrupts at once. */ ! 805: if (status & RxEarly) { /* Rx early is unused. */ ! 806: vortex_rx(dev); ! 807: outw(AckIntr | RxEarly, ioaddr + EL3_CMD); ! 808: } ! 809: if (status & StatsFull) { /* Empty statistics. */ ! 810: static int DoneDidThat = 0; ! 811: if (vortex_debug > 4) ! 812: printk("%s: Updating stats.\n", dev->name); ! 813: update_stats(ioaddr, dev); ! 814: /* DEBUG HACK: Disable statistics as an interrupt source. */ ! 815: /* This occurs when we have the wrong media type! */ ! 816: if (DoneDidThat == 0 && ! 817: inw(ioaddr + EL3_STATUS) & StatsFull) { ! 818: int win, reg; ! 819: printk("%s: Updating stats failed, disabling stats as an" ! 820: " interrupt source.\n", dev->name); ! 821: for (win = 0; win < 8; win++) { ! 822: EL3WINDOW(win); ! 823: printk("\n Vortex window %d:", win); ! 824: for (reg = 0; reg < 16; reg++) ! 825: printk(" %2.2x", inb(ioaddr+reg)); ! 826: } ! 827: EL3WINDOW(7); ! 828: outw(SetIntrEnb | 0x18, ioaddr + EL3_CMD); ! 829: DoneDidThat++; ! 830: } ! 831: } ! 832: if (status & AdapterFailure) { ! 833: /* Adapter failure requires Rx reset and reinit. */ ! 834: outw(RxReset, ioaddr + EL3_CMD); ! 835: /* Set the Rx filter to the current state. */ ! 836: outw(SetRxFilter | RxStation | RxBroadcast ! 837: | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0) ! 838: | (dev->flags & IFF_PROMISC ? RxProm : 0), ! 839: ioaddr + EL3_CMD); ! 840: outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ ! 841: outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); ! 842: } ! 843: } ! 844: ! 845: if (++i > 10) { ! 846: printk("%s: Infinite loop in interrupt, status %4.4x. " ! 847: "Disabling functions (%4.4x).\n", ! 848: dev->name, status, SetStatusEnb | ((~status) & 0xFE)); ! 849: /* Disable all pending interrupts. */ ! 850: outw(SetStatusEnb | ((~status) & 0xFE), ioaddr + EL3_CMD); ! 851: outw(AckIntr | 0xFF, ioaddr + EL3_CMD); ! 852: break; ! 853: } ! 854: /* Acknowledge the IRQ. */ ! 855: outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); ! 856: ! 857: } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); ! 858: ! 859: if (vortex_debug > 4) ! 860: printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status); ! 861: ! 862: dev->interrupt = 0; ! 863: return; ! 864: } ! 865: ! 866: static int ! 867: vortex_rx(struct device *dev) ! 868: { ! 869: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 870: int ioaddr = dev->base_addr; ! 871: int i; ! 872: short rx_status; ! 873: ! 874: if (vortex_debug > 5) ! 875: printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", ! 876: inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); ! 877: while ((rx_status = inw(ioaddr + RxStatus)) > 0) { ! 878: if (rx_status & 0x4000) { /* Error, update stats. */ ! 879: unsigned char rx_error = inb(ioaddr + RxErrors); ! 880: if (vortex_debug > 4) ! 881: printk(" Rx error: status %2.2x.\n", rx_error); ! 882: vp->stats.rx_errors++; ! 883: if (rx_error & 0x01) vp->stats.rx_over_errors++; ! 884: if (rx_error & 0x02) vp->stats.rx_length_errors++; ! 885: if (rx_error & 0x04) vp->stats.rx_frame_errors++; ! 886: if (rx_error & 0x08) vp->stats.rx_crc_errors++; ! 887: if (rx_error & 0x10) vp->stats.rx_length_errors++; ! 888: } else { ! 889: /* The packet length: up to 4.5K!. */ ! 890: short pkt_len = rx_status & 0x1fff; ! 891: struct sk_buff *skb; ! 892: ! 893: skb = dev_alloc_skb(pkt_len + 5); ! 894: if (vortex_debug > 4) ! 895: printk("Receiving packet size %d status %4.4x.\n", ! 896: pkt_len, rx_status); ! 897: if (skb != NULL) { ! 898: skb->dev = dev; ! 899: skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ ! 900: /* 'skb_put()' points to the start of sk_buff data area. */ ! 901: insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), ! 902: (pkt_len + 3) >> 2); ! 903: skb->protocol = eth_type_trans(skb, dev); ! 904: netif_rx(skb); ! 905: outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ ! 906: /* Wait a limited time to go to next packet. */ ! 907: for (i = 200; i >= 0; i--) ! 908: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 909: break; ! 910: vp->stats.rx_packets++; ! 911: continue; ! 912: } else if (vortex_debug) ! 913: printk("%s: Couldn't allocate a sk_buff of size %d.\n", ! 914: dev->name, pkt_len); ! 915: } ! 916: vp->stats.rx_dropped++; ! 917: outw(RxDiscard, ioaddr + EL3_CMD); ! 918: /* Wait a limited time to skip this packet. */ ! 919: for (i = 200; i >= 0; i--) ! 920: if ( ! inw(ioaddr + EL3_STATUS) & CmdInProgress) ! 921: break; ! 922: } ! 923: ! 924: return 0; ! 925: } ! 926: ! 927: static int ! 928: vortex_close(struct device *dev) ! 929: { ! 930: int ioaddr = dev->base_addr; ! 931: ! 932: dev->start = 0; ! 933: dev->tbusy = 1; ! 934: ! 935: if (vortex_debug > 1) ! 936: printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n", ! 937: dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); ! 938: ! 939: /* Turn off statistics ASAP. We update lp->stats below. */ ! 940: outw(StatsDisable, ioaddr + EL3_CMD); ! 941: ! 942: /* Disable the receiver and transmitter. */ ! 943: outw(RxDisable, ioaddr + EL3_CMD); ! 944: outw(TxDisable, ioaddr + EL3_CMD); ! 945: ! 946: if (dev->if_port == 3) ! 947: /* Turn off thinnet power. Green! */ ! 948: outw(StopCoax, ioaddr + EL3_CMD); ! 949: else if (dev->if_port == 0) { ! 950: /* Disable link beat and jabber, if_port may change ere next open(). */ ! 951: EL3WINDOW(4); ! 952: outw(inw(ioaddr + Wn4_Media) & ~Media_TP, ioaddr + Wn4_Media); ! 953: } ! 954: ! 955: #ifdef USE_SHARED_IRQ ! 956: free_shared_irq(dev->irq, dev); ! 957: #else ! 958: free_irq(dev->irq); ! 959: /* Mmmm, we should diable all interrupt sources here. */ ! 960: irq2dev_map[dev->irq] = 0; ! 961: #endif ! 962: ! 963: update_stats(ioaddr, dev); ! 964: #ifdef MODULE ! 965: MOD_DEC_USE_COUNT; ! 966: #endif ! 967: ! 968: return 0; ! 969: } ! 970: ! 971: static struct enet_statistics * ! 972: vortex_get_stats(struct device *dev) ! 973: { ! 974: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 975: unsigned long flags; ! 976: ! 977: save_flags(flags); ! 978: cli(); ! 979: update_stats(dev->base_addr, dev); ! 980: restore_flags(flags); ! 981: return &vp->stats; ! 982: } ! 983: ! 984: /* Update statistics. ! 985: Unlike with the EL3 we need not worry about interrupts changing ! 986: the window setting from underneath us, but we must still guard ! 987: against a race condition with a StatsUpdate interrupt updating the ! 988: table. This is done by checking that the ASM (!) code generated uses ! 989: atomic updates with '+='. ! 990: */ ! 991: static void update_stats(int ioaddr, struct device *dev) ! 992: { ! 993: struct vortex_private *vp = (struct vortex_private *)dev->priv; ! 994: ! 995: /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ ! 996: /* Switch to the stats window, and read everything. */ ! 997: EL3WINDOW(6); ! 998: vp->stats.tx_carrier_errors += inb(ioaddr + 0); ! 999: vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); ! 1000: /* Multiple collisions. */ inb(ioaddr + 2); ! 1001: vp->stats.collisions += inb(ioaddr + 3); ! 1002: vp->stats.tx_window_errors += inb(ioaddr + 4); ! 1003: vp->stats.rx_fifo_errors += inb(ioaddr + 5); ! 1004: vp->stats.tx_packets += inb(ioaddr + 6); ! 1005: vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; ! 1006: /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ ! 1007: /* Tx deferrals */ inb(ioaddr + 8); ! 1008: /* Don't bother with register 9, an extention of registers 6&7. ! 1009: If we do use the 6&7 values the atomic update assumption above ! 1010: is invalid. */ ! 1011: inw(ioaddr + 10); /* Total Rx and Tx octets. */ ! 1012: inw(ioaddr + 12); ! 1013: /* New: On the Vortex we must also clear the BadSSD counter. */ ! 1014: EL3WINDOW(4); ! 1015: inb(ioaddr + 12); ! 1016: ! 1017: /* We change back to window 7 (not 1) with the Vortex. */ ! 1018: EL3WINDOW(7); ! 1019: return; ! 1020: } ! 1021: ! 1022: /* There are two version of set_multicast_list() to support both v1.2 and ! 1023: v1.4 kernels. */ ! 1024: static void ! 1025: set_multicast_list(struct device *dev) ! 1026: { ! 1027: short ioaddr = dev->base_addr; ! 1028: ! 1029: if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { ! 1030: outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); ! 1031: if (vortex_debug > 3) { ! 1032: printk("%s: Setting Rx multicast mode, %d addresses.\n", ! 1033: dev->name, dev->mc_count); ! 1034: } ! 1035: } else if (dev->flags & IFF_PROMISC) { ! 1036: outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, ! 1037: ioaddr + EL3_CMD); ! 1038: } else ! 1039: outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); ! 1040: } ! 1041: ! 1042: ! 1043: #ifdef MODULE ! 1044: void ! 1045: cleanup_module(void) ! 1046: { ! 1047: struct device *next_dev; ! 1048: ! 1049: /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ ! 1050: while (root_vortex_dev) { ! 1051: next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module; ! 1052: unregister_netdev(root_vortex_dev); ! 1053: release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE); ! 1054: kfree(root_vortex_dev); ! 1055: root_vortex_dev = next_dev; ! 1056: } ! 1057: } ! 1058: #endif /* MODULE */ ! 1059: ! 1060: /* ! 1061: * Local variables: ! 1062: * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c59x.c -o 3c59x.o" ! 1063: * c-indent-level: 4 ! 1064: * tab-width: 4 ! 1065: * End: ! 1066: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.