|
|
1.1 ! root 1: /* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184. ! 2: ! 3: Original: at1700.c (1993-94 by Donald Becker). ! 4: Copyright 1993 United States Government as represented by the ! 5: Director, National Security Agency. ! 6: The author may be reached as [email protected], or C/O ! 7: Center of Excellence in Space Data and Information Sciences ! 8: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! 9: ! 10: Modified by Yutaka TAMIYA ([email protected]) ! 11: Copyright 1994 Fujitsu Laboratories Ltd. ! 12: Special thanks to: ! 13: Masayoshi UTAKA ([email protected]) ! 14: for testing this driver. ! 15: H. NEGISHI (agy, [email protected]) ! 16: for suggestion of some program modification. ! 17: Masahiro SEKIGUCHI <[email protected]> ! 18: for suggestion of some program modification. ! 19: Kazutoshi MORIOKA ([email protected]) ! 20: for testing this driver. ! 21: ! 22: This software may be used and distributed according to the terms ! 23: of the GNU Public License, incorporated herein by reference. ! 24: ! 25: This is a device driver for the Fujitsu FMV-181/182/183/184, which ! 26: is a straight-forward Fujitsu MB86965 implementation. ! 27: ! 28: Sources: ! 29: at1700.c ! 30: The Fujitsu MB86965 datasheet. ! 31: The Fujitsu FMV-181/182 user's guide ! 32: */ ! 33: ! 34: static const char *version = ! 35: "fmv18x.c:v1.3.71e 03/04/96 Yutaka TAMIYA ([email protected])\n"; ! 36: ! 37: #include <linux/module.h> ! 38: ! 39: #include <linux/kernel.h> ! 40: #include <linux/sched.h> ! 41: #include <linux/types.h> ! 42: #include <linux/fcntl.h> ! 43: #include <linux/interrupt.h> ! 44: #include <linux/ptrace.h> ! 45: #include <linux/ioport.h> ! 46: #include <linux/in.h> ! 47: #include <linux/malloc.h> ! 48: #include <linux/string.h> ! 49: #include <asm/system.h> ! 50: #include <asm/bitops.h> ! 51: #include <asm/io.h> ! 52: #include <asm/dma.h> ! 53: #include <linux/errno.h> ! 54: ! 55: #include <linux/netdevice.h> ! 56: #include <linux/etherdevice.h> ! 57: #include <linux/skbuff.h> ! 58: #include <linux/delay.h> ! 59: ! 60: static int fmv18x_probe_list[] = ! 61: {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0}; ! 62: ! 63: /* use 0 for production, 1 for verification, >2 for debug */ ! 64: #ifndef NET_DEBUG ! 65: #define NET_DEBUG 1 ! 66: #endif ! 67: static unsigned int net_debug = NET_DEBUG; ! 68: ! 69: typedef unsigned char uchar; ! 70: ! 71: /* Information that need to be kept for each board. */ ! 72: struct net_local { ! 73: struct enet_statistics stats; ! 74: long open_time; /* Useless example local info. */ ! 75: uint tx_started:1; /* Number of packet on the Tx queue. */ ! 76: uchar tx_queue; /* Number of packet on the Tx queue. */ ! 77: ushort tx_queue_len; /* Current length of the Tx queue. */ ! 78: }; ! 79: ! 80: ! 81: /* Offsets from the base address. */ ! 82: #define STATUS 0 ! 83: #define TX_STATUS 0 ! 84: #define RX_STATUS 1 ! 85: #define TX_INTR 2 /* Bit-mapped interrupt enable registers. */ ! 86: #define RX_INTR 3 ! 87: #define TX_MODE 4 ! 88: #define RX_MODE 5 ! 89: #define CONFIG_0 6 /* Misc. configuration settings. */ ! 90: #define CONFIG_1 7 ! 91: /* Run-time register bank 2 definitions. */ ! 92: #define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */ ! 93: #define TX_START 10 ! 94: #define COL16CNTL 11 ! 95: #define MODE13 13 ! 96: /* Fujitsu FMV-18x Card Configuration */ ! 97: #define FJ_STATUS0 0x10 ! 98: #define FJ_STATUS1 0x11 ! 99: #define FJ_CONFIG0 0x12 ! 100: #define FJ_CONFIG1 0x13 ! 101: #define FJ_MACADDR 0x14 /* 0x14 - 0x19 */ ! 102: #define FJ_BUFCNTL 0x1A ! 103: #define FJ_BUFDATA 0x1C ! 104: #define FMV18X_IO_EXTENT 32 ! 105: ! 106: /* Index to functions, as function prototypes. */ ! 107: ! 108: extern int fmv18x_probe(struct device *dev); ! 109: ! 110: static int fmv18x_probe1(struct device *dev, short ioaddr); ! 111: static int net_open(struct device *dev); ! 112: static int net_send_packet(struct sk_buff *skb, struct device *dev); ! 113: static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); ! 114: static void net_rx(struct device *dev); ! 115: static int net_close(struct device *dev); ! 116: static struct enet_statistics *net_get_stats(struct device *dev); ! 117: static void set_multicast_list(struct device *dev); ! 118: ! 119: ! 120: /* Check for a network adaptor of this type, and return '0' iff one exists. ! 121: If dev->base_addr == 0, probe all likely locations. ! 122: If dev->base_addr == 1, always return failure. ! 123: If dev->base_addr == 2, allocate space for the device and return success ! 124: (detachable devices only). ! 125: */ ! 126: #ifdef HAVE_DEVLIST ! 127: /* Support for a alternate probe manager, which will eliminate the ! 128: boilerplate below. */ ! 129: struct netdev_entry fmv18x_drv = ! 130: {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list}; ! 131: #else ! 132: int ! 133: fmv18x_probe(struct device *dev) ! 134: { ! 135: int i; ! 136: int base_addr = dev ? dev->base_addr : 0; ! 137: ! 138: if (base_addr > 0x1ff) /* Check a single specified location. */ ! 139: return fmv18x_probe1(dev, base_addr); ! 140: else if (base_addr != 0) /* Don't probe at all. */ ! 141: return ENXIO; ! 142: ! 143: for (i = 0; fmv18x_probe_list[i]; i++) { ! 144: int ioaddr = fmv18x_probe_list[i]; ! 145: if (check_region(ioaddr, FMV18X_IO_EXTENT)) ! 146: continue; ! 147: if (fmv18x_probe1(dev, ioaddr) == 0) ! 148: return 0; ! 149: } ! 150: ! 151: return ENODEV; ! 152: } ! 153: #endif ! 154: ! 155: /* The Fujitsu datasheet suggests that the NIC be probed for by checking its ! 156: "signature", the default bit pattern after a reset. This *doesn't* work -- ! 157: there is no way to reset the bus interface without a complete power-cycle! ! 158: ! 159: It turns out that ATI came to the same conclusion I did: the only thing ! 160: that can be done is checking a few bits and then diving right into MAC ! 161: address check. */ ! 162: ! 163: int fmv18x_probe1(struct device *dev, short ioaddr) ! 164: { ! 165: char irqmap[4] = {3, 7, 10, 15}; ! 166: unsigned int i, irq; ! 167: ! 168: /* Resetting the chip doesn't reset the ISA interface, so don't bother. ! 169: That means we have to be careful with the register values we probe for. ! 170: */ ! 171: ! 172: /* Check I/O address configuration and Fujitsu vendor code */ ! 173: if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr ! 174: || inb(ioaddr+FJ_MACADDR ) != 0x00 ! 175: || inb(ioaddr+FJ_MACADDR+1) != 0x00 ! 176: || inb(ioaddr+FJ_MACADDR+2) != 0x0e) ! 177: return -ENODEV; ! 178: ! 179: irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03]; ! 180: ! 181: /* Snarf the interrupt vector now. */ ! 182: if (request_irq(irq, &net_interrupt, 0, "fmv18x", NULL)) { ! 183: printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" ! 184: "IRQ %d.\n", ioaddr, irq); ! 185: return EAGAIN; ! 186: } ! 187: ! 188: /* Allocate a new 'dev' if needed. */ ! 189: if (dev == NULL) ! 190: dev = init_etherdev(0, sizeof(struct net_local)); ! 191: ! 192: /* Grab the region so that we can find another board if the IRQ request ! 193: fails. */ ! 194: request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x"); ! 195: ! 196: printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, ! 197: ioaddr, irq); ! 198: ! 199: dev->base_addr = ioaddr; ! 200: dev->irq = irq; ! 201: irq2dev_map[irq] = dev; ! 202: ! 203: for(i = 0; i < 6; i++) { ! 204: unsigned char val = inb(ioaddr + FJ_MACADDR + i); ! 205: printk("%02x", val); ! 206: dev->dev_addr[i] = val; ! 207: } ! 208: ! 209: /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals, ! 210: rather than 150 ohm shielded twisted pair compensation. ! 211: 0x0000 == auto-sense the interface ! 212: 0x0800 == use TP interface ! 213: 0x1800 == use coax interface ! 214: */ ! 215: { ! 216: const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"}; ! 217: ushort setup_value = inb(ioaddr + FJ_STATUS0); ! 218: ! 219: switch( setup_value & 0x07 ){ ! 220: case 0x01 /* 10base5 */: ! 221: case 0x02 /* 10base2 */: dev->if_port = 0x18; break; ! 222: case 0x04 /* 10baseT */: dev->if_port = 0x08; break; ! 223: default /* auto-sense*/: dev->if_port = 0x00; break; ! 224: } ! 225: printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]); ! 226: } ! 227: ! 228: /* Initialize LAN Controller and LAN Card */ ! 229: outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ ! 230: outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ ! 231: outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ ! 232: outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */ ! 233: ! 234: /* wait for a while */ ! 235: udelay(200); ! 236: ! 237: /* Set the station address in bank zero. */ ! 238: outb(0x00, ioaddr + CONFIG_1); ! 239: for (i = 0; i < 6; i++) ! 240: outb(dev->dev_addr[i], ioaddr + 8 + i); ! 241: ! 242: /* Switch to bank 1 and set the multicast table to accept none. */ ! 243: outb(0x04, ioaddr + CONFIG_1); ! 244: for (i = 0; i < 8; i++) ! 245: outb(0x00, ioaddr + 8 + i); ! 246: ! 247: /* Switch to bank 2 and lock our I/O address. */ ! 248: outb(0x08, ioaddr + CONFIG_1); ! 249: outb(dev->if_port, ioaddr + MODE13); ! 250: ! 251: if (net_debug) ! 252: printk(version); ! 253: ! 254: /* Initialize the device structure. */ ! 255: dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); ! 256: if (dev->priv == NULL) ! 257: return -ENOMEM; ! 258: memset(dev->priv, 0, sizeof(struct net_local)); ! 259: ! 260: dev->open = net_open; ! 261: dev->stop = net_close; ! 262: dev->hard_start_xmit = net_send_packet; ! 263: dev->get_stats = net_get_stats; ! 264: dev->set_multicast_list = &set_multicast_list; ! 265: ! 266: /* Fill in the fields of 'dev' with ethernet-generic values. */ ! 267: ! 268: ether_setup(dev); ! 269: return 0; ! 270: } ! 271: ! 272: ! 273: static int net_open(struct device *dev) ! 274: { ! 275: struct net_local *lp = (struct net_local *)dev->priv; ! 276: int ioaddr = dev->base_addr; ! 277: ! 278: /* Set the configuration register 0 to 32K 100ns. byte-wide memory, ! 279: 16 bit bus access, and two 4K Tx, enable the Rx and Tx. */ ! 280: outb(0x5a, ioaddr + CONFIG_0); ! 281: ! 282: /* Powerup and switch to register bank 2 for the run-time registers. */ ! 283: outb(0xe8, ioaddr + CONFIG_1); ! 284: ! 285: lp->tx_started = 0; ! 286: lp->tx_queue = 0; ! 287: lp->tx_queue_len = 0; ! 288: ! 289: /* Clear Tx and Rx Status */ ! 290: outb(0xff, ioaddr + TX_STATUS); ! 291: outb(0xff, ioaddr + RX_STATUS); ! 292: lp->open_time = jiffies; ! 293: ! 294: dev->tbusy = 0; ! 295: dev->interrupt = 0; ! 296: dev->start = 1; ! 297: ! 298: /* Enable the IRQ of the LAN Card */ ! 299: outb(0x80, ioaddr + FJ_CONFIG1); ! 300: ! 301: /* Enable both Tx and Rx interrupts */ ! 302: outw(0x8182, ioaddr+TX_INTR); ! 303: ! 304: MOD_INC_USE_COUNT; ! 305: ! 306: return 0; ! 307: } ! 308: ! 309: static int ! 310: net_send_packet(struct sk_buff *skb, struct device *dev) ! 311: { ! 312: struct net_local *lp = (struct net_local *)dev->priv; ! 313: int ioaddr = dev->base_addr; ! 314: ! 315: if (dev->tbusy) { ! 316: /* If we get here, some higher level has decided we are broken. ! 317: There should really be a "kick me" function call instead. */ ! 318: int tickssofar = jiffies - dev->trans_start; ! 319: if (tickssofar < 10) ! 320: return 1; ! 321: printk("%s: transmit timed out with status %04x, %s?\n", dev->name, ! 322: htons(inw(ioaddr + TX_STATUS)), ! 323: inb(ioaddr + TX_STATUS) & 0x80 ! 324: ? "IRQ conflict" : "network cable problem"); ! 325: printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", ! 326: dev->name, htons(inw(ioaddr + 0)), ! 327: htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), ! 328: htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), ! 329: htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), ! 330: htons(inw(ioaddr +14))); ! 331: printk("eth card: %04x %04x\n", ! 332: htons(inw(ioaddr+FJ_STATUS0)), ! 333: htons(inw(ioaddr+FJ_CONFIG0))); ! 334: lp->stats.tx_errors++; ! 335: /* ToDo: We should try to restart the adaptor... */ ! 336: cli(); ! 337: ! 338: /* Initialize LAN Controller and LAN Card */ ! 339: outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ ! 340: outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ ! 341: outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ ! 342: outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ ! 343: net_open(dev); ! 344: ! 345: sti(); ! 346: } ! 347: ! 348: /* If some higher layer thinks we've missed an tx-done interrupt ! 349: we are passed NULL. Caution: dev_tint() handles the cli()/sti() ! 350: itself. */ ! 351: if (skb == NULL) { ! 352: dev_tint(dev); ! 353: return 0; ! 354: } ! 355: ! 356: /* Block a timer-based transmit from overlapping. This could better be ! 357: done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ ! 358: if (set_bit(0, (void*)&dev->tbusy) != 0) ! 359: printk("%s: Transmitter access conflict.\n", dev->name); ! 360: else { ! 361: short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; ! 362: unsigned char *buf = skb->data; ! 363: ! 364: if (length > ETH_FRAME_LEN) { ! 365: if (net_debug) ! 366: printk("%s: Attempting to send a large packet (%d bytes).\n", ! 367: dev->name, length); ! 368: return 1; ! 369: } ! 370: ! 371: if (net_debug > 4) ! 372: printk("%s: Transmitting a packet of length %lu.\n", dev->name, ! 373: (unsigned long)skb->len); ! 374: ! 375: /* Disable both interrupts. */ ! 376: outw(0x0000, ioaddr + TX_INTR); ! 377: ! 378: outw(length, ioaddr + DATAPORT); ! 379: outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); ! 380: ! 381: lp->tx_queue++; ! 382: lp->tx_queue_len += length + 2; ! 383: ! 384: if (lp->tx_started == 0) { ! 385: /* If the Tx is idle, always trigger a transmit. */ ! 386: outb(0x80 | lp->tx_queue, ioaddr + TX_START); ! 387: lp->tx_queue = 0; ! 388: lp->tx_queue_len = 0; ! 389: dev->trans_start = jiffies; ! 390: lp->tx_started = 1; ! 391: dev->tbusy = 0; ! 392: } else if (lp->tx_queue_len < 4096 - 1502) ! 393: /* Yes, there is room for one more packet. */ ! 394: dev->tbusy = 0; ! 395: ! 396: /* Re-enable interrupts */ ! 397: outw(0x8182, ioaddr + TX_INTR); ! 398: } ! 399: dev_kfree_skb (skb, FREE_WRITE); ! 400: ! 401: return 0; ! 402: } ! 403: ! 404: /* The typical workload of the driver: ! 405: Handle the network interface interrupts. */ ! 406: static void ! 407: net_interrupt(int irq, void *dev_id, struct pt_regs *regs) ! 408: { ! 409: struct device *dev = (struct device *)(irq2dev_map[irq]); ! 410: struct net_local *lp; ! 411: int ioaddr, status; ! 412: ! 413: if (dev == NULL) { ! 414: printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq); ! 415: return; ! 416: } ! 417: dev->interrupt = 1; ! 418: ! 419: ioaddr = dev->base_addr; ! 420: lp = (struct net_local *)dev->priv; ! 421: ! 422: /* Avoid multiple interrupts. */ ! 423: outw(0x0000, ioaddr + TX_INTR); ! 424: ! 425: status = inw(ioaddr + TX_STATUS); ! 426: outw(status, ioaddr + TX_STATUS); ! 427: ! 428: if (net_debug > 4) ! 429: printk("%s: Interrupt with status %04x.\n", dev->name, status); ! 430: if (status & 0xff00 ! 431: || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */ ! 432: net_rx(dev); ! 433: } ! 434: if (status & 0x00ff) { ! 435: if (status & 0x80) { ! 436: lp->stats.tx_packets++; ! 437: if (lp->tx_queue) { ! 438: outb(0x80 | lp->tx_queue, ioaddr + TX_START); ! 439: lp->tx_queue = 0; ! 440: lp->tx_queue_len = 0; ! 441: dev->trans_start = jiffies; ! 442: dev->tbusy = 0; ! 443: mark_bh(NET_BH); /* Inform upper layers. */ ! 444: } else { ! 445: lp->tx_started = 0; ! 446: dev->tbusy = 0; ! 447: mark_bh(NET_BH); /* Inform upper layers. */ ! 448: } ! 449: } ! 450: if (status & 0x02 ) { ! 451: if (net_debug > 4) ! 452: printk("%s: 16 Collision occur during Txing.\n", dev->name); ! 453: /* Retry to send the packet */ ! 454: outb(0x02, ioaddr + COL16CNTL); ! 455: } ! 456: } ! 457: ! 458: dev->interrupt = 0; ! 459: outw(0x8182, ioaddr + TX_INTR); ! 460: return; ! 461: } ! 462: ! 463: /* We have a good packet(s), get it/them out of the buffers. */ ! 464: static void ! 465: net_rx(struct device *dev) ! 466: { ! 467: struct net_local *lp = (struct net_local *)dev->priv; ! 468: int ioaddr = dev->base_addr; ! 469: int boguscount = 10; /* 5 -> 10: by agy 19940922 */ ! 470: ! 471: while ((inb(ioaddr + RX_MODE) & 0x40) == 0) { ! 472: /* Clear PKT_RDY bit: by agy 19940922 */ ! 473: /* outb(0x80, ioaddr + RX_STATUS); */ ! 474: ushort status = inw(ioaddr + DATAPORT); ! 475: ! 476: if (net_debug > 4) ! 477: printk("%s: Rxing packet mode %02x status %04x.\n", ! 478: dev->name, inb(ioaddr + RX_MODE), status); ! 479: #ifndef final_version ! 480: if (status == 0) { ! 481: outb(0x05, ioaddr + 14); ! 482: break; ! 483: } ! 484: #endif ! 485: ! 486: if ((status & 0xF0) != 0x20) { /* There was an error. */ ! 487: lp->stats.rx_errors++; ! 488: if (status & 0x08) lp->stats.rx_length_errors++; ! 489: if (status & 0x04) lp->stats.rx_frame_errors++; ! 490: if (status & 0x02) lp->stats.rx_crc_errors++; ! 491: if (status & 0x01) lp->stats.rx_over_errors++; ! 492: } else { ! 493: ushort pkt_len = inw(ioaddr + DATAPORT); ! 494: /* Malloc up new buffer. */ ! 495: struct sk_buff *skb; ! 496: ! 497: if (pkt_len > 1550) { ! 498: printk("%s: The FMV-18x claimed a very large packet, size %d.\n", ! 499: dev->name, pkt_len); ! 500: outb(0x05, ioaddr + 14); ! 501: lp->stats.rx_errors++; ! 502: break; ! 503: } ! 504: skb = dev_alloc_skb(pkt_len+3); ! 505: if (skb == NULL) { ! 506: printk("%s: Memory squeeze, dropping packet (len %d).\n", ! 507: dev->name, pkt_len); ! 508: outb(0x05, ioaddr + 14); ! 509: lp->stats.rx_dropped++; ! 510: break; ! 511: } ! 512: skb->dev = dev; ! 513: skb_reserve(skb,2); ! 514: ! 515: insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1); ! 516: ! 517: if (net_debug > 5) { ! 518: int i; ! 519: printk("%s: Rxed packet of length %d: ", dev->name, pkt_len); ! 520: for (i = 0; i < 14; i++) ! 521: printk(" %02x", skb->data[i]); ! 522: printk(".\n"); ! 523: } ! 524: ! 525: skb->protocol=eth_type_trans(skb, dev); ! 526: netif_rx(skb); ! 527: lp->stats.rx_packets++; ! 528: } ! 529: if (--boguscount <= 0) ! 530: break; ! 531: } ! 532: ! 533: /* If any worth-while packets have been received, dev_rint() ! 534: has done a mark_bh(NET_BH) for us and will work on them ! 535: when we get to the bottom-half routine. */ ! 536: { ! 537: int i; ! 538: for (i = 0; i < 20; i++) { ! 539: if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40) ! 540: break; ! 541: (void)inw(ioaddr + DATAPORT); /* dummy status read */ ! 542: outb(0x05, ioaddr + 14); ! 543: } ! 544: ! 545: if (net_debug > 5 && i > 0) ! 546: printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", ! 547: dev->name, inb(ioaddr + RX_MODE), i); ! 548: } ! 549: ! 550: return; ! 551: } ! 552: ! 553: /* The inverse routine to net_open(). */ ! 554: static int net_close(struct device *dev) ! 555: { ! 556: int ioaddr = dev->base_addr; ! 557: ! 558: ((struct net_local *)dev->priv)->open_time = 0; ! 559: ! 560: dev->tbusy = 1; ! 561: dev->start = 0; ! 562: ! 563: /* Set configuration register 0 to disable Tx and Rx. */ ! 564: outb(0xda, ioaddr + CONFIG_0); ! 565: ! 566: /* Update the statistics -- ToDo. */ ! 567: ! 568: /* Power-down the chip. Green, green, green! */ ! 569: outb(0x00, ioaddr + CONFIG_1); ! 570: ! 571: MOD_DEC_USE_COUNT; ! 572: ! 573: /* Set the ethernet adaptor disable IRQ */ ! 574: outb(0x00, ioaddr + FJ_CONFIG1); ! 575: ! 576: return 0; ! 577: } ! 578: ! 579: /* Get the current statistics. This may be called with the card open or ! 580: closed. */ ! 581: static struct enet_statistics * ! 582: net_get_stats(struct device *dev) ! 583: { ! 584: struct net_local *lp = (struct net_local *)dev->priv; ! 585: ! 586: cli(); ! 587: /* ToDo: Update the statistics from the device registers. */ ! 588: sti(); ! 589: ! 590: return &lp->stats; ! 591: } ! 592: ! 593: /* Set or clear the multicast filter for this adaptor. ! 594: num_addrs == -1 Promiscuous mode, receive all packets ! 595: num_addrs == 0 Normal mode, clear multicast list ! 596: num_addrs > 0 Multicast mode, receive normal and MC packets, and do ! 597: best-effort filtering. ! 598: */ ! 599: static void ! 600: set_multicast_list(struct device *dev) ! 601: { ! 602: short ioaddr = dev->base_addr; ! 603: if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) ! 604: { ! 605: /* ! 606: * We must make the kernel realise we had to move ! 607: * into promisc mode or we start all out war on ! 608: * the cable. - AC ! 609: */ ! 610: dev->flags|=IFF_PROMISC; ! 611: ! 612: outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ ! 613: } ! 614: else ! 615: outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */ ! 616: } ! 617: ! 618: #ifdef MODULE ! 619: static char devicename[9] = { 0, }; ! 620: static struct device dev_fmv18x = { ! 621: devicename, /* device name is inserted by linux/drivers/net/net_init.c */ ! 622: 0, 0, 0, 0, ! 623: 0, 0, ! 624: 0, 0, 0, NULL, fmv18x_probe }; ! 625: ! 626: static int io = 0x220; ! 627: static int irq = 0; ! 628: ! 629: int init_module(void) ! 630: { ! 631: if (io == 0) ! 632: printk("fmv18x: You should not use auto-probing with insmod!\n"); ! 633: dev_fmv18x.base_addr = io; ! 634: dev_fmv18x.irq = irq; ! 635: if (register_netdev(&dev_fmv18x) != 0) { ! 636: printk("fmv18x: register_netdev() returned non-zero.\n"); ! 637: return -EIO; ! 638: } ! 639: return 0; ! 640: } ! 641: ! 642: void ! 643: cleanup_module(void) ! 644: { ! 645: unregister_netdev(&dev_fmv18x); ! 646: kfree(dev_fmv18x.priv); ! 647: dev_fmv18x.priv = NULL; ! 648: ! 649: /* If we don't do this, we can't re-insmod it later. */ ! 650: free_irq(dev_fmv18x.irq, NULL); ! 651: irq2dev_map[dev_fmv18x.irq] = NULL; ! 652: release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT); ! 653: } ! 654: #endif /* MODULE */ ! 655: ! 656: /* ! 657: * Local variables: ! 658: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c" ! 659: * version-control: t ! 660: * kept-new-versions: 5 ! 661: * tab-width: 4 ! 662: * c-indent-level: 4 ! 663: * End: ! 664: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.