*** fmv18x.c Thu May 16 22:35:40 1996 --- at1700.c Tue Apr 14 13:12:25 1998 *************** *** 1,38 **** ! /* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184. ! Original: at1700.c (1993-94 by Donald Becker). ! Copyright 1993 United States Government as represented by the ! Director, National Security Agency. ! The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O ! Center of Excellence in Space Data and Information Sciences ! Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! ! Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp) ! Copyright 1994 Fujitsu Laboratories Ltd. ! Special thanks to: ! Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp) ! for testing this driver. ! H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp) ! for suggestion of some program modification. ! Masahiro SEKIGUCHI ! for suggestion of some program modification. ! Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp) ! for testing this driver. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. ! This is a device driver for the Fujitsu FMV-181/182/183/184, which ! is a straight-forward Fujitsu MB86965 implementation. ! Sources: ! at1700.c ! The Fujitsu MB86965 datasheet. ! The Fujitsu FMV-181/182 user's guide */ ! static const char *version = ! "fmv18x.c:v1.3.71e 03/04/96 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n"; #include --- 1,40 ---- ! /* at1700.c (tentative name): A network device driver for ! the FMV-181/182/183/184 and the AT1700/RE2000 series. ! Original: fmv18x.c (1994 by Yutaka TAMIYA). ! Modified by Hiroaki Nagoya (nagoya@is.titech.ac.jp) This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. ! This is a device driver for the AT1700/RE2000 series and the FMV-18x ! series, which is a straight-forward Fujitsu MB86965 implementation. ! Sources: ! at1700.c (by D. Becker) ! fmv18x.c (by Y. Tamiya) ! if_fe.c (by M. Seki, in FreeBSD kernel source) ! The Fujitsu MB86965 datasheet ! ! History: ! 97/03/25 1st release (based on fmv18x.c) ! 97/11/22 Fixed 16collision problem (I`m not sure ...) ! 97/11/22 Merged with fmv18x driver ! 97/11/25 Fixed missing IRQ enabler for FMV-18x (by Y. TAMIYA) ! 97/12/04 Fixed bug of interface recognition ! 98/01/28 Fixed bug of IRQ selection for AT1700 (by T. Nakamura) ! 98/04/12 Supported kernel version 2.1.84 */ ! #include ! #if (LINUX_VERSION_CODE < 0x200ff) /* for v2.0.x */ ! #define KERNEL_MAJOR_VERSION 20 ! #elif (LINUX_VERSION_CODE < 0x201ff) /* for v2.1.x */ ! #define KERNEL_MAJOR_VERSION 21 ! #endif ! ! static const char version[] = ! "at1700.c:v$Revision: 0.9.2.4 $ $Date: 1998/04/14 04:11:51 $ $Author: nagoya $"; #include *************** *** 46,51 **** --- 48,56 ---- #include #include #include + #if (KERNEL_MAJOR_VERSION == 21) + #include + #endif #include #include #include *************** *** 57,83 **** #include #include - static int fmv18x_probe_list[] = - {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0}; - /* use 0 for production, 1 for verification, >2 for debug */ #ifndef NET_DEBUG ! #define NET_DEBUG 1 #endif static unsigned int net_debug = NET_DEBUG; typedef unsigned char uchar; ! /* Information that need to be kept for each board. */ struct net_local { ! struct enet_statistics stats; long open_time; /* Useless example local info. */ uint tx_started:1; /* Number of packet on the Tx queue. */ uchar tx_queue; /* Number of packet on the Tx queue. */ ushort tx_queue_len; /* Current length of the Tx queue. */ }; - /* Offsets from the base address. */ #define STATUS 0 #define TX_STATUS 0 --- 62,99 ---- #include #include /* use 0 for production, 1 for verification, >2 for debug */ #ifndef NET_DEBUG ! #define NET_DEBUG 1 #endif + + /* use check for probe functions (NAGOYA) */ + #define MB86965_DEBUG + /* for test (NAGOYA) */ + #define mb86965_probe at1700_probe /* If at1700.c replace by this */ + //#define mb86965_probe fmv18x_probe /* If fmv18x.c replace by this */ + + #if (KERNEL_MAJOR_VERSION == 20) + #define __initdata + #define net_device_stats enet_statistics + #define __initfunc(func) func + #define test_and_set_bit(a,b) set_bit(a,b) + #endif + static unsigned int net_debug = NET_DEBUG; typedef unsigned char uchar; ! /* Information that need to be kept for each board. */ struct net_local { ! struct net_device_stats stats; long open_time; /* Useless example local info. */ uint tx_started:1; /* Number of packet on the Tx queue. */ uchar tx_queue; /* Number of packet on the Tx queue. */ ushort tx_queue_len; /* Current length of the Tx queue. */ + const char *cardtype; /* Assign card type (NAGOYA) */ }; /* Offsets from the base address. */ #define STATUS 0 #define TX_STATUS 0 *************** *** 93,98 **** --- 109,151 ---- #define TX_START 10 #define COL16CNTL 11 #define MODE13 13 + #define EEPROM_Ctrl 16 + #define EEPROM_Data 17 + #define IOCONFIG 19 + #define RESET 31 /* Write to reset some parts of the chip. */ + #define MB86965_IO_EXTENT 32 + + /* EEPROM_Ctrl bits. */ + #define EE_SHIFT_CLK 0x40 /* EEPROM shift clock, in reg. 16. */ + #define EE_CS 0x20 /* EEPROM chip select, in reg. 16. */ + #define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ + #define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ + + /* Delay between EEPROM clock transitions. */ + #define eeprom_delay() \ + do { int _i = 40; while (--_i > 0) { inb(0x80); }} while (0) + + /* The EEPROM commands include the alway-set leading bit. */ + #define EE_WRITE_CMD (5 << 6) + #define EE_READ_CMD (6 << 6) + #define EE_ERASE_CMD (7 << 6) + + #define MB86965_BMPR19 19 + #define MB86965_B19_IRQ 0xC0 + #define MB86965_B19_IRQ_SHIFT 6 + /* EEPROM allocation (offsets) of AT1700/RE2000. */ + #define MB86965_ATI_EEP_ADDR 0x08 /* Station address. (8-13) */ + #define MB86965_ATI_EEP_MEDIA 0x18 /* Media type. */ + #define MB86965_ATI_EEP_MAGIC 0x19 /* XXX Magic. */ + #define MB86965_ATI_EEP_MODEL 0x1e /* Hardware type. */ + #define MB86965_ATI_EEP_REVISION 0x1f /* Hardware revision. */ + + #define MB86965_ATI_MODEL_AT1700T 00 + #define MB86965_ATI_MODEL_AT1700BT 01 + #define MB86965_ATI_MODEL_AT1700FT 02 + #define MB86965_ATI_MODEL_AT1700AT 03 + + /* Fujitsu FMV-18x Card Configuration */ #define FJ_STATUS0 0x10 #define FJ_STATUS1 0x11 *************** *** 101,121 **** #define FJ_MACADDR 0x14 /* 0x14 - 0x19 */ #define FJ_BUFCNTL 0x1A #define FJ_BUFDATA 0x1C - #define FMV18X_IO_EXTENT 32 /* Index to functions, as function prototypes. */ ! extern int fmv18x_probe(struct device *dev); static int fmv18x_probe1(struct device *dev, short ioaddr); static int net_open(struct device *dev); ! static int net_send_packet(struct sk_buff *skb, struct device *dev); static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void net_rx(struct device *dev); static int net_close(struct device *dev); ! static struct enet_statistics *net_get_stats(struct device *dev); static void set_multicast_list(struct device *dev); /* Check for a network adaptor of this type, and return '0' iff one exists. If dev->base_addr == 0, probe all likely locations. --- 154,192 ---- #define FJ_MACADDR 0x14 /* 0x14 - 0x19 */ #define FJ_BUFCNTL 0x1A #define FJ_BUFDATA 0x1C /* Index to functions, as function prototypes. */ ! extern int mb86965_probe(struct device *dev); + static int at1700_probe1(struct device *dev, short ioaddr); static int fmv18x_probe1(struct device *dev, short ioaddr); + static int read_eeprom(int ioaddr, int location); static int net_open(struct device *dev); ! static int net_send_packet(struct sk_buff *skb, struct device *dev); static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void net_rx(struct device *dev); static int net_close(struct device *dev); ! static struct net_device_stats *net_get_stats(struct device *dev); static void set_multicast_list(struct device *dev); + static int at1700_probe_list[] __initdata = + {0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0}; + static int fmv18x_probe_list[] __initdata = + {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0}; + + struct probe_list { + const char *cardtype; + int (*probe)(struct device *dev, short ioaddr); + int *addresses; + }; + static const struct probe_list probe_list[] = { + /* { , } */ + {"fmv18x", fmv18x_probe1, fmv18x_probe_list}, + {"at1700", at1700_probe1, at1700_probe_list}, + {NULL, NULL} + }; + /* Check for a network adaptor of this type, and return '0' iff one exists. If dev->base_addr == 0, probe all likely locations. *************** *** 124,153 **** (detachable devices only). */ #ifdef HAVE_DEVLIST ! /* Support for a alternate probe manager, which will eliminate the boilerplate below. */ ! struct netdev_entry fmv18x_drv = ! {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list}; #else ! int ! fmv18x_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; ! if (base_addr > 0x1ff) /* Check a single specified location. */ ! return fmv18x_probe1(dev, base_addr); ! else if (base_addr != 0) /* Don't probe at all. */ ! return ENXIO; ! for (i = 0; fmv18x_probe_list[i]; i++) { ! int ioaddr = fmv18x_probe_list[i]; ! if (check_region(ioaddr, FMV18X_IO_EXTENT)) ! continue; ! if (fmv18x_probe1(dev, ioaddr) == 0) ! return 0; } return ENODEV; } #endif --- 195,240 ---- (detachable devices only). */ #ifdef HAVE_DEVLIST ! /* Support for an alternate probe manager, which will eliminate the boilerplate below. */ ! /* I don't understand this section, so eliminated this. (NAGOYA)*/ #else ! /* Wrapper probe function (NAGOYA) */ ! __initfunc(int ! mb86965_probe(struct device *dev)) { + const struct probe_list *list; int i; int base_addr = dev ? dev->base_addr : 0; ! #ifdef MB86965_DEBUG ! printk("%s\n", version); ! #endif ! if (base_addr > 0x1ff) { /* Check a single specified location. */ ! for (list = probe_list; list->probe != NULL; list++) { ! int retval; ! if ((retval = list->probe(dev, base_addr)) == 0) { ! ((struct net_local *)dev->priv)->cardtype = list->cardtype; ! return 0; ! } ! } ! return -ENODEV; ! } else if (base_addr != 0) { /* Don't probe at all. */ ! return ENXIO; } + for (list = probe_list; list->probe != NULL; list++) { + for (i = 0; list->addresses[i]; i++) { + int ioaddr = list->addresses[i]; + if (check_region(ioaddr, MB86965_IO_EXTENT)) + continue; + if (list->probe(dev, ioaddr) == 0) { + ((struct net_local *)dev->priv)->cardtype = list->cardtype; + return 0; + } + } + } return ENODEV; } #endif *************** *** 160,170 **** that can be done is checking a few bits and then diving right into MAC address check. */ ! int fmv18x_probe1(struct device *dev, short ioaddr) { char irqmap[4] = {3, 7, 10, 15}; unsigned int i, irq; /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ --- 247,424 ---- that can be done is checking a few bits and then diving right into MAC address check. */ ! /* Stole from at1700.c (NAGOYA) */ ! __initfunc(int ! at1700_probe1(struct device *dev, short ioaddr)) ! { ! char irqmap[][4] = { ! {3, 4, 5, 9}, {10, 11, 14, 15}, {3,11,5,15}, {10,11,14,15}}; ! int n; ! char *model; ! unsigned int i, irq; ! ! #ifdef MB86965_DEBUG ! printk("at1700_probe1(%#x)\n", ioaddr); ! #endif ! ! /* Resetting the chip doesn't reset the ISA interface, so don't bother. ! That means we have to be careful with the register values we probe for. ! */ ! ! /* Check I/O address configuration */ ! if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr ! || read_eeprom(ioaddr,4) != 0x0000 ! || (read_eeprom(ioaddr,5) & 0xff00) != 0xf400) ! return -ENODEV; ! ! /* Reset the internal state machines. */ ! outb(0, ioaddr + RESET); ! ! /* ! * Try to determine IRQ settings. ! * Different models use different ranges of IRQs. ! */ ! n = (inb(ioaddr + IOCONFIG) & MB86965_B19_IRQ) >> MB86965_B19_IRQ_SHIFT; ! switch ((read_eeprom(ioaddr, 15) & 0x00f0)) { ! case 0x30: ! irq = irqmap[3][n]; ! break; ! case 0x10: ! case 0x50: ! irq = irqmap[2][n]; ! break; ! case 0x40: ! case 0x60: ! if ((read_eeprom(ioaddr, 12) & 0x04)) { ! irq = irqmap[1][n]; ! } else { ! irq = irqmap[0][n]; ! } ! break; ! default: ! irq = irqmap[0][n]; ! break; ! } ! ! /* Snarf the interrupt vector now. */ ! if (request_irq(irq, &net_interrupt, 0, "at1700", dev)) { ! printk ("AT1700 found at %#3x, but it's unusable due to a conflict on" ! "IRQ %d.\n", ioaddr, irq); ! return EAGAIN; ! } ! ! /* Allocate a new 'dev' if needed. */ ! if (dev == NULL) ! dev = init_etherdev(0, sizeof(struct net_local)); ! ! /* Grab the region so that we can find another board if the IRQ request ! fails. */ ! request_region(ioaddr, MB86965_IO_EXTENT, "at1700"); ! ! /* Determine the card type. */ ! switch ((read_eeprom(ioaddr, 15)>>8) & 0x07) { ! case MB86965_ATI_MODEL_AT1700T: ! model = "AT1700T/RE2001"; ! break; ! case MB86965_ATI_MODEL_AT1700BT: ! model = "AT1700BT/RE2003"; ! break; ! case MB86965_ATI_MODEL_AT1700FT: ! model = "AT1700FT/RE2009"; ! break; ! case MB86965_ATI_MODEL_AT1700AT: ! model = "AT1700AT/RE2005"; ! break; ! default: ! model = "unknown AT1700/RE2000 ?"; ! break; ! } ! printk("%s: %s found at %#3x, IRQ %d, address ", dev->name, ! model, ioaddr, irq); ! ! dev->base_addr = ioaddr; ! dev->irq = irq; ! #if (KERNEL_MAJOR_VERSION == 20) ! irq2dev_map[irq] = dev; ! #endif ! ! for(i = 0; i < 3; i++) { ! unsigned short eeprom_val = read_eeprom(ioaddr, 4+i); ! printk("%04x", eeprom_val); ! ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val); ! } ! ! /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals, ! rather than 150 ohm shielded twisted pair compensation. ! 0x0000 == auto-sense the interface ! 0x0800 == use TP interface ! 0x1800 == use coax interface ! */ ! { ! const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"}; ! ushort setup_value = read_eeprom(ioaddr, 12); ! ! dev->if_port = setup_value >> 8; ! printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]); ! } ! ! /* Initialize LAN Controller and LAN Card */ ! outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ ! outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ ! ! /* wait for a while */ ! udelay(200); ! ! /* Set the station address in bank zero. */ ! outb(0xe0, ioaddr + CONFIG_1); ! for (i = 0; i < 6; i++) ! outb(dev->dev_addr[i], ioaddr + 8 + i); ! ! /* Switch to bank 1 and set the multicast table to accept none. */ ! outb(0xe4, ioaddr + CONFIG_1); ! for (i = 0; i < 8; i++) ! outb(0x00, ioaddr + 8 + i); ! ! /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit ! bus access, two 4K Tx queues, and disabeld Tx and Rx. */ ! outb(0xda, ioaddr + CONFIG_0); ! ! /* Switch to bank 2 and lock our I/O address. */ ! outb(0xe8, ioaddr + CONFIG_1); ! outb(dev->if_port, ioaddr + MODE13); ! ! if (net_debug) ! printk("%s\n", version); ! ! /* Initialize the device structure. */ ! dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); ! if (dev->priv == NULL) ! return -ENOMEM; ! memset(dev->priv, 0, sizeof(struct net_local)); ! ! dev->open = net_open; ! dev->stop = net_close; ! dev->hard_start_xmit = net_send_packet; ! dev->get_stats = net_get_stats; ! dev->set_multicast_list = &set_multicast_list; ! ! /* Fill in the fields of 'dev' with ethernet-generic values. */ ! ! ether_setup(dev); ! return 0; ! } ! ! /* Stole from fmv18x.c (NAGOYA) */ ! __initfunc(int ! fmv18x_probe1(struct device *dev, short ioaddr)) { char irqmap[4] = {3, 7, 10, 15}; unsigned int i, irq; + #ifdef MB86965_DEBUG + printk("fmv18x_probe1(%#x)\n", ioaddr); + #endif + /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ *************** *** 191,204 **** /* Grab the region so that we can find another board if the IRQ request fails. */ ! request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x"); printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, ioaddr, irq); dev->base_addr = ioaddr; dev->irq = irq; irq2dev_map[irq] = dev; for(i = 0; i < 6; i++) { unsigned char val = inb(ioaddr + FJ_MACADDR + i); --- 445,460 ---- /* Grab the region so that we can find another board if the IRQ request fails. */ ! request_region(ioaddr, MB86965_IO_EXTENT, "fmv18x"); printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, ioaddr, irq); dev->base_addr = ioaddr; dev->irq = irq; + #if (KERNEL_MAJOR_VERSION == 20) irq2dev_map[irq] = dev; + #endif for(i = 0; i < 6; i++) { unsigned char val = inb(ioaddr + FJ_MACADDR + i); *************** *** 228,234 **** /* Initialize LAN Controller and LAN Card */ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ ! outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */ /* wait for a while */ --- 484,490 ---- /* Initialize LAN Controller and LAN Card */ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ ! outb(0x80, ioaddr + FJ_CONFIG1); /* Enable IRQ of LAN Card */ outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */ /* wait for a while */ *************** *** 249,255 **** outb(dev->if_port, ioaddr + MODE13); if (net_debug) ! printk(version); /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); --- 505,511 ---- outb(dev->if_port, ioaddr + MODE13); if (net_debug) ! printk("%s\n", version); /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); *************** *** 270,282 **** } ! static int net_open(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; /* Set the configuration register 0 to 32K 100ns. byte-wide memory, ! 16 bit bus access, and two 4K Tx, enable the Rx and Tx. */ outb(0x5a, ioaddr + CONFIG_0); /* Powerup and switch to register bank 2 for the run-time registers. */ --- 526,581 ---- } ! /* Stole from at1700.c (NAGOYA) */ ! static int ! read_eeprom(int ioaddr, int location) ! { ! int i; ! unsigned short retval = 0; ! short ee_addr = ioaddr + EEPROM_Ctrl; ! short ee_daddr = ioaddr + EEPROM_Data; ! int read_cmd = location | EE_READ_CMD; ! short ctrl_val = EE_CS; ! ! outb(ctrl_val, ee_addr); ! ! /* Shift the read command bits out. */ ! for (i = 9; i >= 0; i--) { ! short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; ! outb(dataval, ee_daddr); ! outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ ! eeprom_delay(); ! outb(EE_CS, ee_addr); /* Finish EEPROM a clock tick. */ ! eeprom_delay(); ! } ! outb(EE_CS, ee_addr); ! ! for (i = 16; i > 0; i--) { ! outb(EE_CS | EE_SHIFT_CLK, ee_addr); ! eeprom_delay(); ! retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0); ! outb(EE_CS, ee_addr); ! eeprom_delay(); ! } ! ! /* Terminate the EEPROM access. */ ! ctrl_val &= ~EE_CS; ! outb(ctrl_val | EE_SHIFT_CLK, ee_addr); ! eeprom_delay(); ! outb(ctrl_val, ee_addr); ! eeprom_delay(); ! return retval; ! } ! ! ! static int ! net_open(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; /* Set the configuration register 0 to 32K 100ns. byte-wide memory, ! 16 bit bus access, two 4K Tx queues, and disabeld Tx and Rx. */ outb(0x5a, ioaddr + CONFIG_0); /* Powerup and switch to register bank 2 for the run-time registers. */ *************** *** 295,303 **** dev->interrupt = 0; dev->start = 1; - /* Enable the IRQ of the LAN Card */ - outb(0x80, ioaddr + FJ_CONFIG1); - /* Enable both Tx and Rx interrupts */ outw(0x8182, ioaddr+TX_INTR); --- 594,599 ---- *************** *** 328,336 **** htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), htons(inw(ioaddr +14))); - printk("eth card: %04x %04x\n", - htons(inw(ioaddr+FJ_STATUS0)), - htons(inw(ioaddr+FJ_CONFIG0))); lp->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ cli(); --- 624,629 ---- *************** *** 338,350 **** /* Initialize LAN Controller and LAN Card */ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ - outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ - outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ net_open(dev); sti(); } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ --- 631,642 ---- /* Initialize LAN Controller and LAN Card */ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ net_open(dev); sti(); } + #if (KERNEL_MAJOR_VERSION == 20) /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ *************** *** 352,361 **** dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ ! if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; --- 644,654 ---- dev_tint(dev); return 0; } + #endif /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ ! if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; *************** *** 406,434 **** static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct device *dev = (struct device *)(irq2dev_map[irq]); ! struct net_local *lp; int ioaddr, status; if (dev == NULL) { ! printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq); return; } dev->interrupt = 1; ioaddr = dev->base_addr; - lp = (struct net_local *)dev->priv; /* Avoid multiple interrupts. */ outw(0x0000, ioaddr + TX_INTR); ! status = inw(ioaddr + TX_STATUS); outw(status, ioaddr + TX_STATUS); if (net_debug > 4) printk("%s: Interrupt with status %04x.\n", dev->name, status); if (status & 0xff00 ! || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */ net_rx(dev); } if (status & 0x00ff) { --- 699,731 ---- static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + #if (KERNEL_MAJOR_VERSION == 20) struct device *dev = (struct device *)(irq2dev_map[irq]); ! #elif (KERNEL_MAJOR_VERSION == 21) ! struct device *dev = dev_id; ! #endif ! struct net_local *lp = (struct net_local *)dev->priv; int ioaddr, status; if (dev == NULL) { ! printk ("%s_interrupt(): irq %d for unknown device.\n", ! lp->cardtype, irq); return; } dev->interrupt = 1; ioaddr = dev->base_addr; /* Avoid multiple interrupts. */ outw(0x0000, ioaddr + TX_INTR); ! status = inw(ioaddr + TX_STATUS); outw(status, ioaddr + TX_STATUS); if (net_debug > 4) printk("%s: Interrupt with status %04x.\n", dev->name, status); if (status & 0xff00 ! || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */ net_rx(dev); } if (status & 0x00ff) { *************** *** 447,457 **** mark_bh(NET_BH); /* Inform upper layers. */ } } ! if (status & 0x02 ) { ! if (net_debug > 4) printk("%s: 16 Collision occur during Txing.\n", dev->name); ! /* Retry to send the packet */ ! outb(0x02, ioaddr + COL16CNTL); } } --- 744,777 ---- mark_bh(NET_BH); /* Inform upper layers. */ } } ! if (status & 0x02 ) { /* Stole from if_fe.c (NAGOYA) */ ! #ifdef MB86965_DEBUG ! /* Find how many packets (including this collided one) ! are left unsent in transmission buffer. */ ! int left = inb(ioaddr + TX_START); ! printk("%s: excessive collision (%d)\n", dev->name, left); ! #endif ! if (net_debug > 4) printk("%s: 16 Collision occur during Txing.\n", dev->name); ! ! /* Clear the collision flag (in 86960) here to avoid ! confusing statistics. */ ! outb(0x04, ioaddr + TX_STATUS); ! ! /* Restart Transmitter, skipping the collided packet. ! ! We *must* skip the packet to keep network running ! properly. Excessive collision error is an ! indication of the network overload. If we ! tried sending the same packet after excessive ! collision, the network would be filled with ! out-of-time packets. Packets belonging ! to reliable transport (such as TCP) are resent ! by some upper layer. */ ! outb(0x03, ioaddr + COL16CNTL); ! ! /* Update statistics */ ! lp->stats.collisions++; } } *************** *** 495,501 **** struct sk_buff *skb; if (pkt_len > 1550) { ! printk("%s: The FMV-18x claimed a very large packet, size %d.\n", dev->name, pkt_len); outb(0x05, ioaddr + 14); lp->stats.rx_errors++; --- 815,821 ---- struct sk_buff *skb; if (pkt_len > 1550) { ! printk("%s: The fe claimed a very large packet, size %d.\n", dev->name, pkt_len); outb(0x05, ioaddr + 14); lp->stats.rx_errors++; *************** *** 551,557 **** } /* The inverse routine to net_open(). */ ! static int net_close(struct device *dev) { int ioaddr = dev->base_addr; --- 871,878 ---- } /* The inverse routine to net_open(). */ ! static int ! net_close(struct device *dev) { int ioaddr = dev->base_addr; *************** *** 570,584 **** MOD_DEC_USE_COUNT; - /* Set the ethernet adaptor disable IRQ */ - outb(0x00, ioaddr + FJ_CONFIG1); - return 0; } /* Get the current statistics. This may be called with the card open or closed. */ ! static struct enet_statistics * net_get_stats(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; --- 891,902 ---- MOD_DEC_USE_COUNT; return 0; } /* Get the current statistics. This may be called with the card open or closed. */ ! static struct net_device_stats * net_get_stats(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; *************** *** 600,605 **** --- 918,924 ---- set_multicast_list(struct device *dev) { short ioaddr = dev->base_addr; + if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) { /* *************** *** 617,639 **** #ifdef MODULE static char devicename[9] = { 0, }; ! static struct device dev_fmv18x = { devicename, /* device name is inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0, 0, ! 0, 0, 0, NULL, fmv18x_probe }; ! static int io = 0x220; static int irq = 0; ! int init_module(void) { if (io == 0) ! printk("fmv18x: You should not use auto-probing with insmod!\n"); ! dev_fmv18x.base_addr = io; ! dev_fmv18x.irq = irq; ! if (register_netdev(&dev_fmv18x) != 0) { ! printk("fmv18x: register_netdev() returned non-zero.\n"); return -EIO; } return 0; --- 936,967 ---- #ifdef MODULE static char devicename[9] = { 0, }; ! static struct device dev_mb86965 = { devicename, /* device name is inserted by linux/drivers/net/net_init.c */ 0, 0, 0, 0, 0, 0, ! 0, 0, 0, NULL, mb86965_probe }; ! static int io = 0x260; static int irq = 0; + static char module_name[] = "fmv18x/at1700"; + + #if (KERNEL_MAJOR_VERSION == 21) + MODULE_PARM(io, "i"); + MODULE_PARM(irq, "i"); + #endif ! int ! init_module(void) { if (io == 0) ! printk("%s: You should not use auto-probing with insmod!\n", ! module_name); ! dev_mb86965.base_addr = io; ! dev_mb86965.irq = irq; ! if (register_netdev(&dev_mb86965) != 0) { ! printk("%s: register_netdev() returned non-zero.\n", ! module_name); return -EIO; } return 0; *************** *** 642,661 **** void cleanup_module(void) { ! unregister_netdev(&dev_fmv18x); ! kfree(dev_fmv18x.priv); ! dev_fmv18x.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ ! free_irq(dev_fmv18x.irq, NULL); ! irq2dev_map[dev_fmv18x.irq] = NULL; ! release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT); } #endif /* MODULE */ /* * Local variables: ! * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c" * version-control: t * kept-new-versions: 5 * tab-width: 4 --- 970,993 ---- void cleanup_module(void) { ! unregister_netdev(&dev_mb86965); ! kfree(dev_mb86965.priv); ! dev_mb86965.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ ! #if (KERNEL_MAJOR_VERSION == 20) ! free_irq(dev_mb86965.irq, NULL); ! irq2dev_map[dev_mb86965.irq] = NULL; ! #elif (KERNEL_MAJOR_VERSION == 21) ! free_irq(dev_mb86965.irq, &dev_mb86965); ! #endif ! release_region(dev_mb86965.base_addr, MB86965_IO_EXTENT); } #endif /* MODULE */ /* * Local variables: ! * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c" * version-control: t * kept-new-versions: 5 * tab-width: 4