From: Alan Cox This is the result of indent -kr -i8 -bri0 so you could just run indent or apply the diff. I plan to fix the exclusive IRQ assumption in the driver so want it readable first and the diffs separate. IRQ changes and some further indent output cleanup will follow once an indented code set is in the tree. Signed-off-by: Alan Cox Cc: Jeff Garzik Cc: Dominik Brodowski Signed-off-by: Andrew Morton --- drivers/net/pcmcia/3c589_cs.c | 1279 ++++++++++++++++---------------- 1 file changed, 668 insertions(+), 611 deletions(-) diff -puN drivers/net/pcmcia/3c589_cs.c~sanitize-3c589_cs drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c~sanitize-3c589_cs +++ a/drivers/net/pcmcia/3c589_cs.c @@ -69,24 +69,27 @@ /* The top five bits written to EL3_CMD are a command, the lower 11 bits are the parameter, if applicable. */ enum c509cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, - TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, - SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11, + TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11, + RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = + 5 << 11, RxDiscard = 8 << 11, + TxEnable = 9 << 11, TxDisable = 10 << 11, TxReset = 11 << 11, + FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11, + SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold = + 17 << 11, + SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, StatsEnable = + 21 << 11, + StatsDisable = 22 << 11, StopCoax = 23 << 11, }; enum c509status { - IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, - TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, - IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 + IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, + TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, + IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 }; /* The SetRxFilter command accepts the following classes: */ enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 + RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; /* Register window 1 offsets, the window used in normal operation. */ @@ -105,15 +108,15 @@ enum RxFilter { #define TX_TIMEOUT ((400*HZ)/1000) struct el3_private { - struct pcmcia_device *p_dev; - dev_node_t node; - struct net_device_stats stats; - /* For transceiver monitoring */ - struct timer_list media; - u16 media_status; - u16 fast_poll; - unsigned long last_irq; - spinlock_t lock; + struct pcmcia_device *p_dev; + dev_node_t node; + struct net_device_stats stats; + /* For transceiver monitoring */ + struct timer_list media; + u16 media_status; + u16 fast_poll; + unsigned long last_irq; + spinlock_t lock; }; static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; @@ -135,7 +138,7 @@ INT_MODULE_PARM(if_port, 0); INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; + DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -151,7 +154,8 @@ static void media_check(unsigned long ar static int el3_config(struct net_device *dev, struct ifmap *map); static int el3_open(struct net_device *dev); static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t el3_interrupt(int irq, void *dev_id, + struct pt_regs *regs); static void update_stats(struct net_device *dev); static struct net_device_stats *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev); @@ -172,47 +176,47 @@ static void tc589_detach(struct pcmcia_d static int tc589_probe(struct pcmcia_device *link) { - struct el3_private *lp; - struct net_device *dev; + struct el3_private *lp; + struct net_device *dev; - DEBUG(0, "3c589_attach()\n"); + DEBUG(0, "3c589_attach()\n"); - /* Create new ethernet device */ - dev = alloc_etherdev(sizeof(struct el3_private)); - if (!dev) - return -ENOMEM; - lp = netdev_priv(dev); - link->priv = dev; - lp->p_dev = link; - - spin_lock_init(&lp->lock); - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = &el3_interrupt; - link->irq.Instance = dev; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; - - /* The EL3-specific entries in the device structure. */ - SET_MODULE_OWNER(dev); - dev->hard_start_xmit = &el3_start_xmit; - dev->set_config = &el3_config; - dev->get_stats = &el3_get_stats; - dev->set_multicast_list = &set_multicast_list; - dev->open = &el3_open; - dev->stop = &el3_close; + /* Create new ethernet device */ + dev = alloc_etherdev(sizeof(struct el3_private)); + if (!dev) + return -ENOMEM; + lp = netdev_priv(dev); + link->priv = dev; + lp->p_dev = link; + + spin_lock_init(&lp->lock); + link->io.NumPorts1 = 16; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.Handler = &el3_interrupt; + link->irq.Instance = dev; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.ConfigIndex = 1; + link->conf.Present = PRESENT_OPTION; + + /* The EL3-specific entries in the device structure. */ + SET_MODULE_OWNER(dev); + dev->hard_start_xmit = &el3_start_xmit; + dev->set_config = &el3_config; + dev->get_stats = &el3_get_stats; + dev->set_multicast_list = &set_multicast_list; + dev->open = &el3_open; + dev->stop = &el3_close; #ifdef HAVE_TX_TIMEOUT - dev->tx_timeout = el3_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + dev->tx_timeout = el3_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; #endif - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - return tc589_config(link); -} /* tc589_attach */ + return tc589_config(link); +} /* tc589_attach */ /*====================================================================== @@ -225,17 +229,17 @@ static int tc589_probe(struct pcmcia_dev static void tc589_detach(struct pcmcia_device *link) { - struct net_device *dev = link->priv; + struct net_device *dev = link->priv; - DEBUG(0, "3c589_detach(0x%p)\n", link); + DEBUG(0, "3c589_detach(0x%p)\n", link); - if (link->dev_node) - unregister_netdev(dev); + if (link->dev_node) + unregister_netdev(dev); - tc589_release(link); + tc589_release(link); - free_netdev(dev); -} /* tc589_detach */ + free_netdev(dev); +} /* tc589_detach */ /*====================================================================== @@ -250,103 +254,111 @@ do { last_fn = (fn); if ((last_ret = (re static int tc589_config(struct pcmcia_device *link) { - struct net_device *dev = link->priv; - struct el3_private *lp = netdev_priv(dev); - tuple_t tuple; - u16 buf[32], *phys_addr; - int last_fn, last_ret, i, j, multi = 0, fifo; - kio_addr_t ioaddr; - char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; - - DEBUG(0, "3c589_config(0x%p)\n", link); + struct net_device *dev = link->priv; + struct el3_private *lp = netdev_priv(dev); + tuple_t tuple; + u16 buf[32], *phys_addr; + int last_fn, last_ret, i, j, multi = 0, fifo; + kio_addr_t ioaddr; + char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + + DEBUG(0, "3c589_config(0x%p)\n", link); + + phys_addr = (u16 *)dev->dev_addr; + tuple.Attributes = 0; + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; + tuple.Attributes = TUPLE_RETURN_COMMON; + + /* Is this a 3c562? */ + if (link->manf_id != MANFID_3COM) + printk(KERN_INFO "3c589_cs: hmmm, is this really a " + "3Com card??\n"); + multi = (link->card_id == PRODID_3COM_3C562); + + /* For the 3c562, the base address must be xx00-xx7f */ + link->io.IOAddrLines = 16; + for (i = j = 0; j < 0x400; j += 0x10) { + if (multi && (j & 0x80)) + continue; + link->io.BasePort1 = j ^ 0x300; + i = pcmcia_request_io(link, &link->io); + if (i == CS_SUCCESS) + break; + } + if (i != CS_SUCCESS) { + cs_error(link, RequestIO, i); + goto failed; + } + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, + pcmcia_request_configuration(link, &link->conf)); + + dev->irq = link->irq.AssignedIRQ; + dev->base_addr = link->io.BasePort1; + ioaddr = dev->base_addr; + EL3WINDOW(0); - phys_addr = (u16 *)dev->dev_addr; - tuple.Attributes = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - tuple.Attributes = TUPLE_RETURN_COMMON; - - /* Is this a 3c562? */ - if (link->manf_id != MANFID_3COM) - printk(KERN_INFO "3c589_cs: hmmm, is this really a " - "3Com card??\n"); - multi = (link->card_id == PRODID_3COM_3C562); - - /* For the 3c562, the base address must be xx00-xx7f */ - link->io.IOAddrLines = 16; - for (i = j = 0; j < 0x400; j += 0x10) { - if (multi && (j & 0x80)) continue; - link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link, &link->io); - if (i == CS_SUCCESS) break; - } - if (i != CS_SUCCESS) { - cs_error(link, RequestIO, i); - goto failed; - } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - - dev->irq = link->irq.AssignedIRQ; - dev->base_addr = link->io.BasePort1; - ioaddr = dev->base_addr; - EL3WINDOW(0); - - /* The 3c589 has an extra EEPROM for configuration info, including - the hardware address. The 3c562 puts the address in the CIS. */ - tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { - pcmcia_get_tuple_data(link, &tuple); - for (i = 0; i < 3; i++) - phys_addr[i] = htons(buf[i]); - } else { - for (i = 0; i < 3; i++) - phys_addr[i] = htons(read_eeprom(ioaddr, i)); - if (phys_addr[0] == 0x6060) { - printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" - "-0x%03lx\n", dev->base_addr, dev->base_addr+15); - goto failed; - } - } - - /* The address and resource configuration register aren't loaded from - the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ - outw(0x3f00, ioaddr + 8); - fifo = inl(ioaddr); - - /* The if_port symbol can be set when the module is loaded */ - if ((if_port >= 0) && (if_port <= 3)) - dev->if_port = if_port; - else - printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); - - link->dev_node = &lp->node; - SET_NETDEV_DEV(dev, &handle_to_dev(link)); + /* + * The 3c589 has an extra EEPROM for configuration info, including + * the hardware address. The 3c562 puts the address in the CIS. + */ + tuple.DesiredTuple = 0x88; + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { + pcmcia_get_tuple_data(link, &tuple); + for (i = 0; i < 3; i++) + phys_addr[i] = htons(buf[i]); + } else { + for (i = 0; i < 3; i++) + phys_addr[i] = htons(read_eeprom(ioaddr, i)); + if (phys_addr[0] == 0x6060) { + printk(KERN_ERR "3c589_cs: IO port conflict at 0x%03lx" + "-0x%03lx\n", + dev->base_addr, dev->base_addr+15); + goto failed; + } + } + + /* + * The address and resource configuration register aren't loaded from + * the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. + */ + outw(0x3f00, ioaddr + 8); + fifo = inl(ioaddr); + + /* The if_port symbol can be set when the module is loaded */ + if ((if_port >= 0) && (if_port <= 3)) + dev->if_port = if_port; + else + printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); + + link->dev_node = &lp->node; + SET_NETDEV_DEV(dev, &handle_to_dev(link)); + + if (register_netdev(dev) != 0) { + printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); + link->dev_node = NULL; + goto failed; + } - if (register_netdev(dev) != 0) { - printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); - link->dev_node = NULL; - goto failed; - } - - strcpy(lp->node.dev_name, dev->name); - - printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ", - dev->name, (multi ? "562" : "589"), dev->base_addr, - dev->irq); - for (i = 0; i < 6; i++) - printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", - (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], - if_names[dev->if_port]); - return 0; + strcpy(lp->node.dev_name, dev->name); + + printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ", + dev->name, (multi ? "562" : "589"), dev->base_addr, + dev->irq); + for (i = 0; i < 6; i++) + printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); + printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", + (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], + if_names[dev->if_port]); + return 0; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: - tc589_release(link); - return -ENODEV; + tc589_release(link); + return -ENODEV; } /* tc589_config */ /*====================================================================== @@ -376,7 +388,7 @@ static int tc589_resume(struct pcmcia_de { struct net_device *dev = link->priv; - if (link->open) { + if (link->open) { tc589_reset(dev); netif_device_attach(dev); } @@ -391,13 +403,15 @@ static int tc589_resume(struct pcmcia_de */ static void tc589_wait_for_completion(struct net_device *dev, int cmd) { - int i = 100; - outw(cmd, dev->base_addr + EL3_CMD); - while (--i > 0) - if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; - if (i == 0) - printk(KERN_WARNING "%s: command 0x%04x did not complete!\n", - dev->name, cmd); + int i = 100; + outw(cmd, dev->base_addr + EL3_CMD); + while (--i > 0) + if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) + break; + if (i == 0) + printk(KERN_WARNING + "%s: command 0x%04x did not complete!\n", dev->name, + cmd); } /* @@ -406,13 +420,13 @@ static void tc589_wait_for_completion(st */ static u16 read_eeprom(kio_addr_t ioaddr, int index) { - int i; - outw(EEPROM_READ + index, ioaddr + 10); - /* Reading the eeprom takes 162 us */ - for (i = 1620; i >= 0; i--) - if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) - break; - return inw(ioaddr + 12); + int i; + outw(EEPROM_READ + index, ioaddr + 10); + /* Reading the eeprom takes 162 us */ + for (i = 1620; i >= 0; i--) + if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) + break; + return inw(ioaddr + 12); } /* @@ -421,82 +435,90 @@ static u16 read_eeprom(kio_addr_t ioaddr */ static void tc589_set_xcvr(struct net_device *dev, int if_port) { - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; - - EL3WINDOW(0); - switch (if_port) { - case 0: case 1: outw(0, ioaddr + 6); break; - case 2: outw(3<<14, ioaddr + 6); break; - case 3: outw(1<<14, ioaddr + 6); break; - } - /* On PCMCIA, this just turns on the LED */ - outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD); - /* 10baseT interface, enable link beat and jabber check. */ - EL3WINDOW(4); - outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA); - EL3WINDOW(1); - if (if_port == 2) - lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000); - else - lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800); + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + + EL3WINDOW(0); + switch (if_port) { + case 0: + case 1: + outw(0, ioaddr + 6); + break; + case 2: + outw(3 << 14, ioaddr + 6); + break; + case 3: + outw(1 << 14, ioaddr + 6); + break; + } + /* On PCMCIA, this just turns on the LED */ + outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD); + /* 10baseT interface, enable link beat and jabber check. */ + EL3WINDOW(4); + outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), + ioaddr + WN4_MEDIA); + EL3WINDOW(1); + if (if_port == 2) + lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000); + else + lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800); } static void dump_status(struct net_device *dev) { - kio_addr_t ioaddr = dev->base_addr; - EL3WINDOW(1); - printk(KERN_INFO " irq status %04x, rx status %04x, tx status " - "%02x tx free %04x\n", inw(ioaddr+EL3_STATUS), - inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS), - inw(ioaddr+TX_FREE)); - EL3WINDOW(4); - printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x" - " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06), - inw(ioaddr+0x08), inw(ioaddr+0x0a)); - EL3WINDOW(1); + kio_addr_t ioaddr = dev->base_addr; + EL3WINDOW(1); + printk(KERN_INFO " irq status %04x, rx status %04x, tx status " + "%02x tx free %04x\n", inw(ioaddr + EL3_STATUS), + inw(ioaddr + RX_STATUS), inb(ioaddr + TX_STATUS), + inw(ioaddr + TX_FREE)); + EL3WINDOW(4); + printk(KERN_INFO " diagnostics: fifo %04x net %04x ethernet %04x" + " media %04x\n", inw(ioaddr + 0x04), inw(ioaddr + 0x06), + inw(ioaddr + 0x08), inw(ioaddr + 0x0a)); + EL3WINDOW(1); } /* Reset and restore all of the 3c589 registers. */ static void tc589_reset(struct net_device *dev) { - kio_addr_t ioaddr = dev->base_addr; - int i; - - EL3WINDOW(0); - outw(0x0001, ioaddr + 4); /* Activate board. */ - outw(0x3f00, ioaddr + 8); /* Set the IRQ line. */ - - /* Set the station address in window 2. */ - EL3WINDOW(2); - for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + i); + kio_addr_t ioaddr = dev->base_addr; + int i; - tc589_set_xcvr(dev, dev->if_port); - - /* Switch to the stats window, and clear all stats by reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - EL3WINDOW(6); - for (i = 0; i < 9; i++) - inb(ioaddr+i); - inw(ioaddr + 10); - inw(ioaddr + 12); - - /* Switch to register set 1 for normal use. */ - EL3WINDOW(1); + EL3WINDOW(0); + outw(0x0001, ioaddr + 4); /* Activate board. */ + outw(0x3f00, ioaddr + 8); /* Set the IRQ line. */ + + /* Set the station address in window 2. */ + EL3WINDOW(2); + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + i); + + tc589_set_xcvr(dev, dev->if_port); - /* Accept b-cast and phys addr only. */ - outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ - /* Allow status bits to be seen. */ - outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); - /* Ack all pending events, and set active indicator mask. */ - outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, - ioaddr + EL3_CMD); - outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull - | AdapterFailure, ioaddr + EL3_CMD); + /* Switch to the stats window, and clear all stats by reading. */ + outw(StatsDisable, ioaddr + EL3_CMD); + EL3WINDOW(6); + for (i = 0; i < 9; i++) + inb(ioaddr + i); + inw(ioaddr + 10); + inw(ioaddr + 12); + + /* Switch to register set 1 for normal use. */ + EL3WINDOW(1); + + /* Accept b-cast and phys addr only. */ + outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); + outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ + outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ + outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ + /* Allow status bits to be seen. */ + outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); + /* Ack all pending events, and set active indicator mask. */ + outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, + ioaddr + EL3_CMD); + outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull + | AdapterFailure, ioaddr + EL3_CMD); } static void netdev_get_drvinfo(struct net_device *dev, @@ -517,302 +539,317 @@ static void netdev_set_msglevel(struct n { pc_debug = level; } -#endif /* PCMCIA_DEBUG */ +#endif /* PCMCIA_DEBUG */ static struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, + .get_drvinfo = netdev_get_drvinfo, #ifdef PCMCIA_DEBUG - .get_msglevel = netdev_get_msglevel, - .set_msglevel = netdev_set_msglevel, -#endif /* PCMCIA_DEBUG */ + .get_msglevel = netdev_get_msglevel, + .set_msglevel = netdev_set_msglevel, +#endif /* PCMCIA_DEBUG */ }; static int el3_config(struct net_device *dev, struct ifmap *map) { - if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { - if (map->port <= 3) { - dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", - dev->name, if_names[dev->if_port]); - tc589_set_xcvr(dev, dev->if_port); - } else - return -EINVAL; - } - return 0; + if ((map->port != (u_char) (-1)) && (map->port != dev->if_port)) { + if (map->port <= 3) { + dev->if_port = map->port; + printk(KERN_INFO "%s: switched to %s port\n", + dev->name, if_names[dev->if_port]); + tc589_set_xcvr(dev, dev->if_port); + } else + return -EINVAL; + } + return 0; } static int el3_open(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - struct pcmcia_device *link = lp->p_dev; - - if (!pcmcia_dev_present(link)) - return -ENODEV; + struct el3_private *lp = netdev_priv(dev); + struct pcmcia_device *link = lp->p_dev; - link->open++; - netif_start_queue(dev); - - tc589_reset(dev); - init_timer(&lp->media); - lp->media.function = &media_check; - lp->media.data = (unsigned long) dev; - lp->media.expires = jiffies + HZ; - add_timer(&lp->media); + if (!pcmcia_dev_present(link)) + return -ENODEV; - DEBUG(1, "%s: opened, status %4.4x.\n", - dev->name, inw(dev->base_addr + EL3_STATUS)); - - return 0; + link->open++; + netif_start_queue(dev); + + tc589_reset(dev); + init_timer(&lp->media); + lp->media.function = &media_check; + lp->media.data = (unsigned long) dev; + lp->media.expires = jiffies + HZ; + add_timer(&lp->media); + + DEBUG(1, "%s: opened, status %4.4x.\n", + dev->name, inw(dev->base_addr + EL3_STATUS)); + + return 0; } static void el3_tx_timeout(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; - - printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name); - dump_status(dev); - lp->stats.tx_errors++; - dev->trans_start = jiffies; - /* Issue TX_RESET and TX_START commands. */ - tc589_wait_for_completion(dev, TxReset); - outw(TxEnable, ioaddr + EL3_CMD); - netif_wake_queue(dev); + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + + printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name); + dump_status(dev); + lp->stats.tx_errors++; + dev->trans_start = jiffies; + /* Issue TX_RESET and TX_START commands. */ + tc589_wait_for_completion(dev, TxReset); + outw(TxEnable, ioaddr + EL3_CMD); + netif_wake_queue(dev); } static void pop_tx_status(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; - int i; - - /* Clear the Tx status stack. */ - for (i = 32; i > 0; i--) { - u_char tx_status = inb(ioaddr + TX_STATUS); - if (!(tx_status & 0x84)) break; - /* reset transmitter on jabber error or underrun */ - if (tx_status & 0x30) - tc589_wait_for_completion(dev, TxReset); - if (tx_status & 0x38) { - DEBUG(1, "%s: transmit error: status 0x%02x\n", - dev->name, tx_status); - outw(TxEnable, ioaddr + EL3_CMD); - lp->stats.tx_aborted_errors++; + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + int i; + + /* Clear the Tx status stack. */ + for (i = 32; i > 0; i--) { + u_char tx_status = inb(ioaddr + TX_STATUS); + if (!(tx_status & 0x84)) + break; + /* reset transmitter on jabber error or underrun */ + if (tx_status & 0x30) + tc589_wait_for_completion(dev, TxReset); + if (tx_status & 0x38) { + DEBUG(1, "%s: transmit error: status 0x%02x\n", + dev->name, tx_status); + outw(TxEnable, ioaddr + EL3_CMD); + lp->stats.tx_aborted_errors++; + } + outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ } - outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ - } } static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev) { - kio_addr_t ioaddr = dev->base_addr; - struct el3_private *priv = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + struct el3_private *priv = netdev_priv(dev); - DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " - "status %4.4x.\n", dev->name, (long)skb->len, - inw(ioaddr + EL3_STATUS)); - - priv->stats.tx_bytes += skb->len; - - /* Put out the doubleword header... */ - outw(skb->len, ioaddr + TX_FIFO); - outw(0x00, ioaddr + TX_FIFO); - /* ... and the packet rounded to a doubleword. */ - outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " + "status %4.4x.\n", dev->name, (long) skb->len, + inw(ioaddr + EL3_STATUS)); + + priv->stats.tx_bytes += skb->len; + + /* Put out the doubleword header... */ + outw(skb->len, ioaddr + TX_FIFO); + outw(0x00, ioaddr + TX_FIFO); + /* ... and the packet rounded to a doubleword. */ + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + + dev->trans_start = jiffies; + if (inw(ioaddr + TX_FREE) <= 1536) { + netif_stop_queue(dev); + /* Interrupt us when the FIFO has room for max-sized packet. */ + outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); + } - dev->trans_start = jiffies; - if (inw(ioaddr + TX_FREE) <= 1536) { - netif_stop_queue(dev); - /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); - } + dev_kfree_skb(skb); + pop_tx_status(dev); - dev_kfree_skb(skb); - pop_tx_status(dev); - - return 0; + return 0; } /* The EL3 interrupt handler. */ -static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t el3_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { - struct net_device *dev = (struct net_device *) dev_id; - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr; - __u16 status; - int i = 0, handled = 1; - - if (!netif_device_present(dev)) - return IRQ_NONE; + struct net_device *dev = (struct net_device *) dev_id; + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr; + __u16 status; + int i = 0, handled = 1; + + if (!netif_device_present(dev)) + return IRQ_NONE; + + ioaddr = dev->base_addr; + + DEBUG(3, "%s: interrupt, status %4.4x.\n", + dev->name, inw(ioaddr + EL3_STATUS)); + + spin_lock(&lp->lock); + while ((status = inw(ioaddr + EL3_STATUS)) & + (IntLatch | RxComplete | StatsFull)) { + if ((status & 0xe000) != 0x2000) { + DEBUG(1, "%s: interrupt from dead card\n", + dev->name); + handled = 0; + break; + } - ioaddr = dev->base_addr; + if (status & RxComplete) + el3_rx(dev); - DEBUG(3, "%s: interrupt, status %4.4x.\n", - dev->name, inw(ioaddr + EL3_STATUS)); + if (status & TxAvailable) { + DEBUG(3, " TX room bit was handled.\n"); + /* There's room in the FIFO for a full-sized packet. */ + outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); + netif_wake_queue(dev); + } - spin_lock(&lp->lock); - while ((status = inw(ioaddr + EL3_STATUS)) & - (IntLatch | RxComplete | StatsFull)) { - if ((status & 0xe000) != 0x2000) { - DEBUG(1, "%s: interrupt from dead card\n", dev->name); - handled = 0; - break; - } - - if (status & RxComplete) - el3_rx(dev); - - if (status & TxAvailable) { - DEBUG(3, " TX room bit was handled.\n"); - /* There's room in the FIFO for a full-sized packet. */ - outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - netif_wake_queue(dev); - } - - if (status & TxComplete) - pop_tx_status(dev); - - if (status & (AdapterFailure | RxEarly | StatsFull)) { - /* Handle all uncommon interrupts. */ - if (status & StatsFull) /* Empty statistics. */ - update_stats(dev); - if (status & RxEarly) { /* Rx early is unused. */ - el3_rx(dev); - outw(AckIntr | RxEarly, ioaddr + EL3_CMD); - } - if (status & AdapterFailure) { - u16 fifo_diag; - EL3WINDOW(4); - fifo_diag = inw(ioaddr + 4); - EL3WINDOW(1); - printk(KERN_WARNING "%s: adapter failure, FIFO diagnostic" - " register %04x.\n", dev->name, fifo_diag); - if (fifo_diag & 0x0400) { - /* Tx overrun */ - tc589_wait_for_completion(dev, TxReset); - outw(TxEnable, ioaddr + EL3_CMD); + if (status & TxComplete) + pop_tx_status(dev); + + if (status & (AdapterFailure | RxEarly | StatsFull)) { + /* Handle all uncommon interrupts. */ + if (status & StatsFull) /* Empty statistics. */ + update_stats(dev); + if (status & RxEarly) { /* Rx early is unused. */ + el3_rx(dev); + outw(AckIntr | RxEarly, ioaddr + EL3_CMD); + } + if (status & AdapterFailure) { + u16 fifo_diag; + EL3WINDOW(4); + fifo_diag = inw(ioaddr + 4); + EL3WINDOW(1); + printk(KERN_WARNING + "%s: adapter failure, FIFO diagnostic" + " register %04x.\n", dev->name, + fifo_diag); + if (fifo_diag & 0x0400) { + /* Tx overrun */ + tc589_wait_for_completion(dev, + TxReset); + outw(TxEnable, ioaddr + EL3_CMD); + } + if (fifo_diag & 0x2000) { + /* Rx underrun */ + tc589_wait_for_completion(dev, + RxReset); + set_multicast_list(dev); + outw(RxEnable, ioaddr + EL3_CMD); + } + outw(AckIntr | AdapterFailure, + ioaddr + EL3_CMD); + } } - if (fifo_diag & 0x2000) { - /* Rx underrun */ - tc589_wait_for_completion(dev, RxReset); - set_multicast_list(dev); - outw(RxEnable, ioaddr + EL3_CMD); + + if (++i > 10) { + printk(KERN_ERR "%s: infinite loop in interrupt, " + "status %4.4x.\n", dev->name, status); + /* Clear all interrupts */ + outw(AckIntr | 0xFF, ioaddr + EL3_CMD); + break; } - outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); - } + /* Acknowledge the IRQ. */ + outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); } - - if (++i > 10) { - printk(KERN_ERR "%s: infinite loop in interrupt, " - "status %4.4x.\n", dev->name, status); - /* Clear all interrupts */ - outw(AckIntr | 0xFF, ioaddr + EL3_CMD); - break; - } - /* Acknowledge the IRQ. */ - outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - } - - lp->last_irq = jiffies; - spin_unlock(&lp->lock); - DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", - dev->name, inw(ioaddr + EL3_STATUS)); - return IRQ_RETVAL(handled); + + lp->last_irq = jiffies; + spin_unlock(&lp->lock); + DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", + dev->name, inw(ioaddr + EL3_STATUS)); + return IRQ_RETVAL(handled); } static void media_check(unsigned long arg) { - struct net_device *dev = (struct net_device *)(arg); - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; - u16 media, errs; - unsigned long flags; - - if (!netif_device_present(dev)) goto reschedule; - - EL3WINDOW(1); - /* Check for pending interrupt with expired latency timer: with - this, we can limp along even if the interrupt is blocked */ - if ((inw(ioaddr + EL3_STATUS) & IntLatch) && - (inb(ioaddr + EL3_TIMER) == 0xff)) { - if (!lp->fast_poll) - printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name); - el3_interrupt(dev->irq, lp, NULL); - lp->fast_poll = HZ; - } - if (lp->fast_poll) { - lp->fast_poll--; - lp->media.expires = jiffies + HZ/100; - add_timer(&lp->media); - return; - } + struct net_device *dev = (struct net_device *) (arg); + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + u16 media, errs; + unsigned long flags; + + if (!netif_device_present(dev)) + goto reschedule; + + EL3WINDOW(1); + /* Check for pending interrupt with expired latency timer: with + this, we can limp along even if the interrupt is blocked */ + if ((inw(ioaddr + EL3_STATUS) & IntLatch) && + (inb(ioaddr + EL3_TIMER) == 0xff)) { + if (!lp->fast_poll) + printk(KERN_WARNING "%s: interrupt(s) dropped!\n", + dev->name); + el3_interrupt(dev->irq, lp, NULL); + lp->fast_poll = HZ; + } + if (lp->fast_poll) { + lp->fast_poll--; + lp->media.expires = jiffies + HZ / 100; + add_timer(&lp->media); + return; + } - /* lp->lock guards the EL3 window. Window should always be 1 except - when the lock is held */ - spin_lock_irqsave(&lp->lock, flags); - EL3WINDOW(4); - media = inw(ioaddr+WN4_MEDIA) & 0xc810; - - /* Ignore collisions unless we've had no irq's recently */ - if (time_before(jiffies, lp->last_irq + HZ)) { - media &= ~0x0010; - } else { - /* Try harder to detect carrier errors */ - EL3WINDOW(6); - outw(StatsDisable, ioaddr + EL3_CMD); - errs = inb(ioaddr + 0); - outw(StatsEnable, ioaddr + EL3_CMD); - lp->stats.tx_carrier_errors += errs; - if (errs || (lp->media_status & 0x0010)) media |= 0x0010; - } - - if (media != lp->media_status) { - if ((media & lp->media_status & 0x8000) && - ((lp->media_status ^ media) & 0x0800)) - printk(KERN_INFO "%s: %s link beat\n", dev->name, - (lp->media_status & 0x0800 ? "lost" : "found")); - else if ((media & lp->media_status & 0x4000) && - ((lp->media_status ^ media) & 0x0010)) - printk(KERN_INFO "%s: coax cable %s\n", dev->name, - (lp->media_status & 0x0010 ? "ok" : "problem")); - if (dev->if_port == 0) { - if (media & 0x8000) { - if (media & 0x0800) - printk(KERN_INFO "%s: flipped to 10baseT\n", - dev->name); - else - tc589_set_xcvr(dev, 2); - } else if (media & 0x4000) { - if (media & 0x0010) - tc589_set_xcvr(dev, 1); - else - printk(KERN_INFO "%s: flipped to 10base2\n", - dev->name); - } + /* lp->lock guards the EL3 window. Window should always be 1 except + when the lock is held */ + spin_lock_irqsave(&lp->lock, flags); + EL3WINDOW(4); + media = inw(ioaddr + WN4_MEDIA) & 0xc810; + + /* Ignore collisions unless we've had no irq's recently */ + if (time_before(jiffies, lp->last_irq + HZ)) { + media &= ~0x0010; + } else { + /* Try harder to detect carrier errors */ + EL3WINDOW(6); + outw(StatsDisable, ioaddr + EL3_CMD); + errs = inb(ioaddr + 0); + outw(StatsEnable, ioaddr + EL3_CMD); + lp->stats.tx_carrier_errors += errs; + if (errs || (lp->media_status & 0x0010)) + media |= 0x0010; } - lp->media_status = media; - } - - EL3WINDOW(1); - spin_unlock_irqrestore(&lp->lock, flags); + + if (media != lp->media_status) { + if ((media & lp->media_status & 0x8000) && + ((lp->media_status ^ media) & 0x0800)) + printk(KERN_INFO "%s: %s link beat\n", dev->name, + (lp-> + media_status & 0x0800 ? "lost" : "found")); + else if ((media & lp->media_status & 0x4000) + && ((lp->media_status ^ media) & 0x0010)) + printk(KERN_INFO "%s: coax cable %s\n", dev->name, + (lp-> + media_status & 0x0010 ? "ok" : "problem")); + if (dev->if_port == 0) { + if (media & 0x8000) { + if (media & 0x0800) + printk(KERN_INFO + "%s: flipped to 10baseT\n", + dev->name); + else + tc589_set_xcvr(dev, 2); + } else if (media & 0x4000) { + if (media & 0x0010) + tc589_set_xcvr(dev, 1); + else + printk(KERN_INFO + "%s: flipped to 10base2\n", + dev->name); + } + } + lp->media_status = media; + } + + EL3WINDOW(1); + spin_unlock_irqrestore(&lp->lock, flags); reschedule: - lp->media.expires = jiffies + HZ; - add_timer(&lp->media); + lp->media.expires = jiffies + HZ; + add_timer(&lp->media); } static struct net_device_stats *el3_get_stats(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - unsigned long flags; - struct pcmcia_device *link = lp->p_dev; - - if (pcmcia_dev_present(link)) { - spin_lock_irqsave(&lp->lock, flags); - update_stats(dev); - spin_unlock_irqrestore(&lp->lock, flags); - } - return &lp->stats; + struct el3_private *lp = netdev_priv(dev); + unsigned long flags; + struct pcmcia_device *link = lp->p_dev; + + if (pcmcia_dev_present(link)) { + spin_lock_irqsave(&lp->lock, flags); + update_stats(dev); + spin_unlock_irqrestore(&lp->lock, flags); + } + return &lp->stats; } /* @@ -825,163 +862,183 @@ static struct net_device_stats *el3_get_ */ static void update_stats(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; - DEBUG(2, "%s: updating the statistics.\n", dev->name); - /* Turn off statistics updates while reading. */ - outw(StatsDisable, ioaddr + EL3_CMD); - /* Switch to the stats window, and read everything. */ - EL3WINDOW(6); - lp->stats.tx_carrier_errors += inb(ioaddr + 0); - lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - lp->stats.collisions += inb(ioaddr + 3); - lp->stats.tx_window_errors += inb(ioaddr + 4); - lp->stats.rx_fifo_errors += inb(ioaddr + 5); - lp->stats.tx_packets += inb(ioaddr + 6); - /* Rx packets */ inb(ioaddr + 7); - /* Tx deferrals */ inb(ioaddr + 8); - /* Rx octets */ inw(ioaddr + 10); - /* Tx octets */ inw(ioaddr + 12); - - /* Back to window 1, and turn statistics back on. */ - EL3WINDOW(1); - outw(StatsEnable, ioaddr + EL3_CMD); + DEBUG(2, "%s: updating the statistics.\n", dev->name); + /* Turn off statistics updates while reading. */ + outw(StatsDisable, ioaddr + EL3_CMD); + /* Switch to the stats window, and read everything. */ + EL3WINDOW(6); + lp->stats.tx_carrier_errors += inb(ioaddr + 0); + lp->stats.tx_heartbeat_errors += inb(ioaddr + 1); + /* Multiple collisions. */ inb(ioaddr + 2); + lp->stats.collisions += inb(ioaddr + 3); + lp->stats.tx_window_errors += inb(ioaddr + 4); + lp->stats.rx_fifo_errors += inb(ioaddr + 5); + lp->stats.tx_packets += inb(ioaddr + 6); + /* Rx packets */ inb(ioaddr + 7); + /* Tx deferrals */ inb(ioaddr + 8); + /* Rx octets */ inw(ioaddr + 10); + /* Tx octets */ inw(ioaddr + 12); + + /* Back to window 1, and turn statistics back on. */ + EL3WINDOW(1); + outw(StatsEnable, ioaddr + EL3_CMD); } static int el3_rx(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - kio_addr_t ioaddr = dev->base_addr; - int worklimit = 32; - short rx_status; - - DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", - dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); - while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) && - (--worklimit >= 0)) { - if (rx_status & 0x4000) { /* Error, update stats. */ - short error = rx_status & 0x3800; - lp->stats.rx_errors++; - switch (error) { - case 0x0000: lp->stats.rx_over_errors++; break; - case 0x0800: lp->stats.rx_length_errors++; break; - case 0x1000: lp->stats.rx_frame_errors++; break; - case 0x1800: lp->stats.rx_length_errors++; break; - case 0x2000: lp->stats.rx_frame_errors++; break; - case 0x2800: lp->stats.rx_crc_errors++; break; - } - } else { - short pkt_len = rx_status & 0x7ff; - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+5); - - DEBUG(3, " Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); - if (skb != NULL) { - skb->dev = dev; - skb_reserve(skb, 2); - insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len), - (pkt_len+3)>>2); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->last_rx = jiffies; - lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; - } else { - DEBUG(1, "%s: couldn't allocate a sk_buff of" - " size %d.\n", dev->name, pkt_len); - lp->stats.rx_dropped++; - } - } - /* Pop the top of the Rx FIFO */ - tc589_wait_for_completion(dev, RxDiscard); - } - if (worklimit == 0) - printk(KERN_WARNING "%s: too much work in el3_rx!\n", dev->name); - return 0; + struct el3_private *lp = netdev_priv(dev); + kio_addr_t ioaddr = dev->base_addr; + int worklimit = 32; + short rx_status; + + DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", + dev->name, inw(ioaddr + EL3_STATUS), + inw(ioaddr + RX_STATUS)); + while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) + && (--worklimit >= 0)) { + if (rx_status & 0x4000) { /* Error, update stats. */ + short error = rx_status & 0x3800; + lp->stats.rx_errors++; + switch (error) { + case 0x0000: + lp->stats.rx_over_errors++; + break; + case 0x0800: + lp->stats.rx_length_errors++; + break; + case 0x1000: + lp->stats.rx_frame_errors++; + break; + case 0x1800: + lp->stats.rx_length_errors++; + break; + case 0x2000: + lp->stats.rx_frame_errors++; + break; + case 0x2800: + lp->stats.rx_crc_errors++; + break; + } + } else { + short pkt_len = rx_status & 0x7ff; + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len + 5); + + DEBUG(3, + " Receiving packet size %d status %4.4x.\n", + pkt_len, rx_status); + if (skb != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); + insl(ioaddr + RX_FIFO, + skb_put(skb, pkt_len), + (pkt_len + 3) >> 2); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + lp->stats.rx_packets++; + lp->stats.rx_bytes += pkt_len; + } else { + DEBUG(1, + "%s: couldn't allocate a sk_buff of" + " size %d.\n", dev->name, pkt_len); + lp->stats.rx_dropped++; + } + } + /* Pop the top of the Rx FIFO */ + tc589_wait_for_completion(dev, RxDiscard); + } + if (worklimit == 0) + printk(KERN_WARNING "%s: too much work in el3_rx!\n", + dev->name); + return 0; } static void set_multicast_list(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - struct pcmcia_device *link = lp->p_dev; - kio_addr_t ioaddr = dev->base_addr; - u16 opts = SetRxFilter | RxStation | RxBroadcast; - - if (!pcmcia_dev_present(link)) return; - if (dev->flags & IFF_PROMISC) - opts |= RxMulticast | RxProm; - else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) - opts |= RxMulticast; - outw(opts, ioaddr + EL3_CMD); + struct el3_private *lp = netdev_priv(dev); + struct pcmcia_device *link = lp->p_dev; + kio_addr_t ioaddr = dev->base_addr; + u16 opts = SetRxFilter | RxStation | RxBroadcast; + + if (!pcmcia_dev_present(link)) + return; + if (dev->flags & IFF_PROMISC) + opts |= RxMulticast | RxProm; + else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) + opts |= RxMulticast; + outw(opts, ioaddr + EL3_CMD); } static int el3_close(struct net_device *dev) { - struct el3_private *lp = netdev_priv(dev); - struct pcmcia_device *link = lp->p_dev; - kio_addr_t ioaddr = dev->base_addr; - - DEBUG(1, "%s: shutting down ethercard.\n", dev->name); + struct el3_private *lp = netdev_priv(dev); + struct pcmcia_device *link = lp->p_dev; + kio_addr_t ioaddr = dev->base_addr; + + DEBUG(1, "%s: shutting down ethercard.\n", dev->name); + + if (pcmcia_dev_present(link)) { + /* Turn off statistics ASAP. We update lp->stats below. */ + outw(StatsDisable, ioaddr + EL3_CMD); + + /* Disable the receiver and transmitter. */ + outw(RxDisable, ioaddr + EL3_CMD); + outw(TxDisable, ioaddr + EL3_CMD); + + if (dev->if_port == 2) + /* Turn off thinnet power. Green! */ + outw(StopCoax, ioaddr + EL3_CMD); + else if (dev->if_port == 1) { + /* Disable link beat and jabber */ + EL3WINDOW(4); + outw(0, ioaddr + WN4_MEDIA); + } - if (pcmcia_dev_present(link)) { - /* Turn off statistics ASAP. We update lp->stats below. */ - outw(StatsDisable, ioaddr + EL3_CMD); - - /* Disable the receiver and transmitter. */ - outw(RxDisable, ioaddr + EL3_CMD); - outw(TxDisable, ioaddr + EL3_CMD); - - if (dev->if_port == 2) - /* Turn off thinnet power. Green! */ - outw(StopCoax, ioaddr + EL3_CMD); - else if (dev->if_port == 1) { - /* Disable link beat and jabber */ - EL3WINDOW(4); - outw(0, ioaddr + WN4_MEDIA); + /* Switching back to window 0 disables the IRQ. */ + EL3WINDOW(0); + /* But we explicitly zero the IRQ line select anyway. */ + outw(0x0f00, ioaddr + WN0_IRQ); + + /* Check if the card still exists */ + if ((inw(ioaddr + EL3_STATUS) & 0xe000) == 0x2000) + update_stats(dev); } - - /* Switching back to window 0 disables the IRQ. */ - EL3WINDOW(0); - /* But we explicitly zero the IRQ line select anyway. */ - outw(0x0f00, ioaddr + WN0_IRQ); - - /* Check if the card still exists */ - if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000) - update_stats(dev); - } - - link->open--; - netif_stop_queue(dev); - del_timer_sync(&lp->media); - - return 0; + + link->open--; + netif_stop_queue(dev); + del_timer_sync(&lp->media); + + return 0; } static struct pcmcia_device_id tc589_ids[] = { PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), - PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), + PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, + 0x992c2202), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), PCMCIA_DEVICE_NULL, }; + MODULE_DEVICE_TABLE(pcmcia, tc589_ids); static struct pcmcia_driver tc589_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "3c589_cs", - }, - .probe = tc589_probe, - .remove = tc589_detach, - .id_table = tc589_ids, - .suspend = tc589_suspend, - .resume = tc589_resume, + .owner = THIS_MODULE, + .drv = { + .name = "3c589_cs", + }, + .probe = tc589_probe, + .remove = tc589_detach, + .id_table = tc589_ids, + .suspend = tc589_suspend, + .resume = tc589_resume, }; static int __init init_tc589(void) _