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