diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-12 23:15:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-12 23:15:27 +0000 |
commit | ae38fd1e4c98588314a42097c5a5e77dcef23561 (patch) | |
tree | f9f10c203bb9e5fbad4810d1f8774c08dfad20ff /drivers/net | |
parent | 466a823d79f41d0713b272e48fd73e494b0588e0 (diff) |
Merge with Linux 2.3.50.
Diffstat (limited to 'drivers/net')
28 files changed, 1292 insertions, 676 deletions
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 5e948c7e7..b333ad08c 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1049,7 +1049,6 @@ static int send_packet(struct net_device *dev, struct sk_buff *skb) static void elp_timeout(struct net_device *dev) { - unsigned long flags; elp_device *adapter = dev->priv; int stat; diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 80f56adf7..d8a5e12af 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -46,6 +46,7 @@ static int max_interrupt_work = 20; #define RX_RING_SIZE 16 #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/version.h> #include <linux/isapnp.h> diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 9e3f72b33..7a14db1ce 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -85,10 +85,7 @@ $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ */ -#ifdef MODULE #include <linux/module.h> -#endif - #include <linux/kernel.h> #include <linux/sched.h> #include <linux/string.h> @@ -902,7 +899,7 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) #ifndef NO_NOPCOMMANDS if (stat & STAT_CNA) { /* CU went 'not ready' */ - if (netif_running(dev->state)) { + if (netif_running(dev)) { printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); } } diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 64edb30c1..b264def30 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -3,6 +3,7 @@ # source drivers/net/arcnet/Config.in +source drivers/net/appletalk/Config.in tristate 'Dummy net driver support' CONFIG_DUMMY tristate 'Bonding driver support' CONFIG_BONDING @@ -131,9 +132,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then fi tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT - if [ "$CONFIG_OBSOLETE" = "y" ]; then - tristate ' CS89x0 support' CONFIG_CS89x0 - fi + tristate ' CS89x0 support' CONFIG_CS89x0 tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS @@ -209,27 +208,6 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then fi fi -# -# AppleTalk -# - -if [ "$CONFIG_ATALK" != "n" ]; then - mainmenu_option next_comment - comment 'Appletalk devices' - dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK - dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK - if [ "$CONFIG_COPS" != "n" ]; then - bool ' Dayna firmware support' CONFIG_COPS_DAYNA - bool ' Tangent firmware support' CONFIG_COPS_TANGENT - fi - dep_tristate 'Appletalk-IP driver support' CONFIG_IPDDP $CONFIG_ATALK - if [ "$CONFIG_IPDDP" != "n" ]; then - bool ' IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP - bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP - fi - endmenu -fi - if [ ! "$CONFIG_PARPORT" = "n" ]; then dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT fi diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6a7b1f06a..fc4bf1922 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,7 +18,7 @@ SUB_DIRS := MOD_SUB_DIRS := MOD_IN_SUB_DIRS := ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan sk98lin \ - arcnet skfp tulip + arcnet skfp tulip appletalk O_TARGET := net.o MOD_LIST_NAME := NET_MODULES @@ -104,6 +104,15 @@ else endif endif +ifeq ($(CONFIG_ATALK),y) +SUB_DIRS += appletalk +MOD_IN_SUB_DIRS += appletalk +else + ifeq ($(CONFIG_ATALK),m) + MOD_IN_SUB_DIRS += appletalk + endif +endif + # # link order important here # @@ -163,8 +172,10 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o # obj-$(CONFIG_AIRONET4500) += aironet4500_core.o +obj-$(CONFIG_AIRONET4500_CS) += aironet4500_core.o obj-$(CONFIG_AIRONET4500_NONCS) += aironet4500_card.o obj-$(CONFIG_AIRONET4500_PROC) += aironet4500_proc.o +obj-$(CONFIG_AIRONET4500_CS) += aironet4500_proc.o obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o obj-$(CONFIG_SEEQ8005) += seeq8005.o @@ -280,9 +291,6 @@ obj-$(CONFIG_A2065) += a2065.o obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o obj-$(CONFIG_CS89x0) += cs89x0.o -obj-$(CONFIG_LTPC) += ltpc.o -obj-$(CONFIG_COPS) += cops.o -obj-$(CONFIG_IPDDP) += ipddp.o obj-$(CONFIG_MACSONIC) += macsonic.o obj-$(CONFIG_MACMACE) += macmace.o obj-$(CONFIG_MAC89x0) += mac89x0.o diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 3587dfe16..9969bcbde 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -83,13 +83,13 @@ * They used the DEC vendor ID by mistake */ #ifndef PCI_DEVICE_ID_FARALLON_PN9000SX -#define PCI_DEVICE_ID_FARALLON_PN9000SX 0x1a +#define PCI_DEVICE_ID_FARALLON_PN9000SX 0x1a #endif #ifndef PCI_VENDOR_ID_SGI -#define PCI_VENDOR_ID_SGI 0x10a9 +#define PCI_VENDOR_ID_SGI 0x10a9 #endif #ifndef PCI_DEVICE_ID_SGI_ACENIC -#define PCI_DEVICE_ID_SGI_ACENIC 0x0009 +#define PCI_DEVICE_ID_SGI_ACENIC 0x0009 #endif #ifndef wmb @@ -100,6 +100,11 @@ #define __exit #endif +#ifndef SMP_CACHE_BYTES +#define SMP_CACHE_BYTES L1_CACHE_BYTES +#endif + + #if (LINUX_VERSION_CODE < 0x02030e) #define net_device device #endif @@ -121,7 +126,7 @@ static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, return virt_ptr; } #define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr) -#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) +#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) #define pci_unmap_single(cookie, address, size, dir) #endif @@ -140,18 +145,22 @@ static inline void netif_start_queue(struct net_device *dev) dev->start = 1; } -#define ace_mark_net_bh(foo) mark_bh(foo) -#define ace_if_busy(dev) dev->tbusy -#define ace_if_running(dev) dev->start -#define ace_if_down(dev) {do{dev->start = 0;}while (0);} +#define ace_mark_net_bh(foo) mark_bh(foo) +#define netif_queue_stopped(dev) dev->tbusy +#define netif_running(dev) dev->start +#define ace_if_down(dev) {do{dev->start = 0;}while (0);} #else #define NET_BH 0 #define ace_mark_net_bh(foo) {do{} while(0);} -#define ace_if_busy(dev) netif_queue_stopped(dev) -#define ace_if_running(dev) netif_running(dev) #define ace_if_down(dev) {do{} while(0);} #endif + +#define ACE_MAX_MOD_PARMS 8 +#define BOARD_IDX_STATIC 0 +#define BOARD_IDX_OVERFLOW -1 + + #include "acenic.h" /* @@ -336,30 +345,41 @@ static inline void netif_start_queue(struct net_device *dev) #define ACE_STD_BUFSIZE (ACE_STD_MTU + ETH_HLEN + 2+4+16) #define ACE_JUMBO_BUFSIZE (ACE_JUMBO_MTU + ETH_HLEN + 2+4+16) -#define DEF_TX_RATIO 24 /* * There seems to be a magic difference in the effect between 995 and 996 * but little difference between 900 and 995 ... no idea why. + * + * There is now a default set of tuning parameters which is set, depending + * on whether or not the user enables Jumbo frames. It's assumed that if + * Jumbo frames are enabled, the user wants optimal tuning for that case. */ -#define DEF_TX_COAL 996 +#define DEF_TX_COAL 400 /* 996 */ #define DEF_TX_MAX_DESC 40 -#define DEF_RX_COAL 1000 +#define DEF_RX_COAL 120 /* 1000 */ #define DEF_RX_MAX_DESC 25 +#define DEF_TX_RATIO 21 /* 24 */ + +#define DEF_JUMBO_TX_COAL 20 +#define DEF_JUMBO_TX_MAX_DESC 60 +#define DEF_JUMBO_RX_COAL 30 +#define DEF_JUMBO_RX_MAX_DESC 6 +#define DEF_JUMBO_TX_RATIO 21 + #define TX_COAL_INTS_ONLY 0 /* seems not worth it */ #define DEF_TRACE 0 -#define DEF_STAT 2 * TICKS_PER_SEC +#define DEF_STAT (2 * TICKS_PER_SEC) -static int link[8] = {0, }; -static int trace[8] = {0, }; -static int tx_coal_tick[8] = {0, }; -static int rx_coal_tick[8] = {0, }; -static int max_tx_desc[8] = {0, }; -static int max_rx_desc[8] = {0, }; -static int tx_ratio[8] = {0, }; -static int dis_pci_mem_inval[8] = {1, 1, 1, 1, 1, 1, 1, 1}; +static int link[ACE_MAX_MOD_PARMS] = {0, }; +static int trace[ACE_MAX_MOD_PARMS] = {0, }; +static int tx_coal_tick[ACE_MAX_MOD_PARMS] = {0, }; +static int rx_coal_tick[ACE_MAX_MOD_PARMS] = {0, }; +static int max_tx_desc[ACE_MAX_MOD_PARMS] = {0, }; +static int max_rx_desc[ACE_MAX_MOD_PARMS] = {0, }; +static int tx_ratio[ACE_MAX_MOD_PARMS] = {0, }; +static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static const char __initdata *version = - "acenic.c: v0.41 02/16/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" + "acenic.c: v0.42 03/02/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; static struct net_device *root_dev = NULL; @@ -469,11 +489,6 @@ int __init acenic_probe (struct net_device *dev) pci_set_master(pdev); -#ifdef __sparc__ - /* NOTE: Cache line size is in 32-bit word units. */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10); -#endif - /* * Remap the regs into kernel space - this is abuse of * dev->base_addr since it was means for I/O port @@ -484,7 +499,6 @@ int __init acenic_probe (struct net_device *dev) #else dev->base_addr = pdev->resource[0].start; #endif - ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); if (!ap->regs) { printk(KERN_ERR "%s: Unable to map I/O register, " @@ -540,8 +554,7 @@ int __init acenic_probe (struct net_device *dev) if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { printk(KERN_ERR "%s: Driver compiled without Tigon I" " support - NIC disabled\n", dev->name); - iounmap(ap->regs); - unregister_netdev(dev); + ace_init_cleanup(dev); continue; } #endif @@ -550,13 +563,17 @@ int __init acenic_probe (struct net_device *dev) continue; #ifdef MODULE - if (ace_init(dev, boards_found)) - continue; + if (boards_found >= ACE_MAX_MOD_PARMS) + ap->board_idx = BOARD_IDX_OVERFLOW; + else + ap->board_idx = boards_found; #else - if (ace_init(dev, -1)) - continue; + ap->board_idx = BOARD_IDX_STATIC; #endif + if (ace_init(dev)) + continue; + boards_found++; } @@ -566,20 +583,16 @@ int __init acenic_probe (struct net_device *dev) * or more boards. Otherwise, return failure (-ENODEV). */ -#ifdef MODULE - return boards_found; -#else if (boards_found > 0) return 0; else return -ENODEV; -#endif } #ifdef MODULE MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>"); -MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver"); +MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); @@ -597,7 +610,7 @@ void __exit ace_module_cleanup(void) while (root_dev) { next = ((struct ace_private *)root_dev->priv)->next; - ap = (struct ace_private *)root_dev->priv; + ap = root_dev->priv; regs = ap->regs; @@ -670,38 +683,26 @@ void __exit ace_module_cleanup(void) } } - ace_free_descriptors(root_dev); - - if (ap->trace_buf) - kfree(ap->trace_buf); - if (ap->info) - pci_free_consistent(ap->pdev, sizeof(struct ace_info), - ap->info, ap->info_dma); - if (ap->skb) - kfree(ap->skb); - if (root_dev->irq) - free_irq(root_dev->irq, root_dev); - unregister_netdev(root_dev); - iounmap(regs); + ace_init_cleanup(root_dev); kfree(root_dev); - root_dev = next; } } +#endif int __init ace_module_init(void) { - int cards; + int status; root_dev = NULL; #ifdef NEW_NETINIT - cards = acenic_probe(); + status = acenic_probe(); #else - cards = acenic_probe(NULL); + status = acenic_probe(NULL); #endif - return cards ? 0 : -ENODEV; + return status; } @@ -717,7 +718,6 @@ void cleanup_module(void) ace_module_cleanup(); } #endif -#endif #if (LINUX_VERSION_CODE >= 0x02032a) @@ -817,10 +817,36 @@ static int ace_allocate_descriptors(struct net_device *dev) fail: /* Clean up. */ + ace_init_cleanup(dev); + return 1; +} + + +/* + * Generic cleanup handling data allocated during init. Used when the + * module is unloaded or if an error occurs during initialization + */ +static void ace_init_cleanup(struct net_device *dev) +{ + struct ace_private *ap; + + ap = dev->priv; + ace_free_descriptors(dev); - iounmap(ap->regs); + + if (ap->info) + pci_free_consistent(ap->pdev, sizeof(struct ace_info), + ap->info, ap->info_dma); + if (ap->skb) + kfree(ap->skb); + if (ap->trace_buf) + kfree(ap->trace_buf); + + if (dev->irq) + free_irq(dev->irq, dev); + unregister_netdev(dev); - return 1; + iounmap(ap->regs); } @@ -840,19 +866,22 @@ static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd) } -static int __init ace_init(struct net_device *dev, int board_idx) +static int __init ace_init(struct net_device *dev) { struct ace_private *ap; struct ace_regs *regs; struct ace_info *info = NULL; unsigned long tmp_ptr, myjif; u32 tig_ver, mac1, mac2, tmp, pci_state; - int ecode = 0; + int board_idx, ecode = 0; short i; + unsigned char cache; ap = dev->priv; regs = ap->regs; + board_idx = ap->board_idx; + /* * aman@sgi.com - its useful to do a NIC reset here to * address the `Firmware not running' problem subsequent @@ -968,6 +997,21 @@ static int __init ace_init(struct net_device *dev, int board_idx) dev->dev_addr[4] = (mac2 >> 8) & 0xff; dev->dev_addr[5] = mac2 & 0xff; + /* + * Looks like this is necessary to deal with on all architectures, + * even this %$#%$# N440BX Intel based thing doesn't get it right. + * Ie. having two NICs in the machine, one will have the cache + * line set at boot time, the other will not. + */ + pci_read_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, &cache); + if ((cache << 2) != SMP_CACHE_BYTES) { + printk(KERN_INFO " PCI cache line size set incorrectly " + "(%i bytes) by BIOS/FW, correcting to %i\n", + (cache << 2), SMP_CACHE_BYTES); + pci_write_config_byte(ap->pdev, PCI_CACHE_LINE_SIZE, + SMP_CACHE_BYTES >> 2); + } + pci_state = readl(®s->PciState); printk(KERN_INFO " PCI bus width: %i bits, speed: %iMHz, " "latency: %i clks\n", @@ -991,19 +1035,20 @@ static int __init ace_init(struct net_device *dev, int board_idx) /* * Tuning parameters only supported for 8 cards */ - if (board_idx > 7 || dis_pci_mem_inval[board_idx]) { + if (board_idx == BOARD_IDX_OVERFLOW || + dis_pci_mem_inval[board_idx]) { if (ap->pci_command & PCI_COMMAND_INVALIDATE) { ap->pci_command &= ~PCI_COMMAND_INVALIDATE; pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); - printk(KERN_INFO "%s: disabling PCI memory " - "write and invalidate\n", dev->name); + printk(KERN_INFO " Disabling PCI memory " + "write and invalidate\n"); } } else if (ap->pci_command & PCI_COMMAND_INVALIDATE) { - printk(KERN_INFO "%s: PCI memory write & invalidate " - "enabled by BIOS, enabling counter " - "measures\n", dev->name); - switch(L1_CACHE_BYTES) { + printk(KERN_INFO " PCI memory write & invalidate " + "enabled by BIOS, enabling counter measures\n"); + + switch(SMP_CACHE_BYTES) { case 16: tmp |= DMA_WRITE_MAX_16; break; @@ -1023,8 +1068,10 @@ static int __init ace_init(struct net_device *dev, int board_idx) } } } + #ifdef __sparc__ - /* On this platform, we know what the best dma settings + /* + * On this platform, we know what the best dma settings * are. We use 64-byte maximum bursts, because if we * burst larger than the cache line size (or even cross * a 64byte boundry in a single burst) the UltraSparc @@ -1034,12 +1081,18 @@ static int __init ace_init(struct net_device *dev, int board_idx) * set will give the PCI controller proper hints about * prefetching. */ - tmp = (tmp & ~(0xfc)); + tmp = tmp & ~DMA_READ_WRITE_MASK; tmp |= DMA_READ_MAX_64; tmp |= DMA_WRITE_MAX_64; #endif writel(tmp, ®s->PciState); + if (!(ap->pci_command & PCI_COMMAND_FAST_BACK)) { + printk(KERN_INFO " Enabling PCI Fast Back to Back\n"); + ap->pci_command |= PCI_COMMAND_FAST_BACK; + pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); + } + /* * Initialize the generic info block and the command+event rings * and the control blocks for the transmit and receive rings @@ -1213,21 +1266,15 @@ static int __init ace_init(struct net_device *dev, int board_idx) writel(1, ®s->AssistState); writel(DEF_STAT, ®s->TuneStatTicks); - - writel(DEF_TX_COAL, ®s->TuneTxCoalTicks); - writel(DEF_TX_MAX_DESC, ®s->TuneMaxTxDesc); - writel(DEF_RX_COAL, ®s->TuneRxCoalTicks); - writel(DEF_RX_MAX_DESC, ®s->TuneMaxRxDesc); writel(DEF_TRACE, ®s->TuneTrace); - writel(DEF_TX_RATIO, ®s->TxBufRat); - if (board_idx >= 8) { - printk(KERN_WARNING "%s: more then 8 NICs detected, " - "ignoring module parameters!\n", dev->name); - board_idx = -1; - } + ace_set_rxtx_parms(dev, 0); - if (board_idx >= 0) { + if (board_idx == BOARD_IDX_OVERFLOW) { + printk(KERN_WARNING "%s: more then %i NICs detected, " + "ignoring module parameters!\n", + dev->name, ACE_MAX_MOD_PARMS); + } else if (board_idx >= 0) { if (tx_coal_tick[board_idx]) writel(tx_coal_tick[board_idx], ®s->TuneTxCoalTicks); @@ -1352,8 +1399,6 @@ static int __init ace_init(struct net_device *dev, int board_idx) writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); writel(0, ®s->Mb0Lo); - free_irq(dev->irq, dev); - dev->irq = 0; ecode = -EBUSY; goto init_error; @@ -1376,27 +1421,63 @@ static int __init ace_init(struct net_device *dev, int board_idx) "the RX mini ring\n", dev->name); } return 0; + init_error: - iounmap(ap->regs); - unregister_netdev(dev); - if (ap->skb) { - kfree(ap->skb); - ap->skb = NULL; - } - if (ap->info) - pci_free_consistent(ap->pdev, sizeof(struct ace_info), - info, ap->info_dma); + ace_init_cleanup(dev); return ecode; } +static void ace_set_rxtx_parms(struct net_device *dev, int jumbo) +{ + struct ace_private *ap; + struct ace_regs *regs; + int board_idx; + + ap = dev->priv; + regs = ap->regs; + + board_idx = ap->board_idx; + + if (board_idx >= 0) { + if (!jumbo) { + if (!tx_coal_tick[board_idx]) + writel(DEF_TX_COAL, ®s->TuneTxCoalTicks); + if (!max_tx_desc[board_idx]) + writel(DEF_TX_MAX_DESC, ®s->TuneMaxTxDesc); + if (!rx_coal_tick[board_idx]) + writel(DEF_RX_COAL, ®s->TuneRxCoalTicks); + if (!max_rx_desc[board_idx]) + writel(DEF_RX_MAX_DESC, ®s->TuneMaxRxDesc); + if (!tx_ratio[board_idx]) + writel(DEF_TX_RATIO, ®s->TxBufRat); + } else { + if (!tx_coal_tick[board_idx]) + writel(DEF_JUMBO_TX_COAL, + ®s->TuneTxCoalTicks); + if (!max_tx_desc[board_idx]) + writel(DEF_JUMBO_TX_MAX_DESC, + ®s->TuneMaxTxDesc); + if (!rx_coal_tick[board_idx]) + writel(DEF_JUMBO_RX_COAL, + ®s->TuneRxCoalTicks); + if (!max_rx_desc[board_idx]) + writel(DEF_JUMBO_RX_MAX_DESC, + ®s->TuneMaxRxDesc); + if (!tx_ratio[board_idx]) + writel(DEF_JUMBO_TX_RATIO, ®s->TxBufRat); + } + } +} + + /* * Monitor the card to detect hangs. */ static void ace_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct ace_private *ap = (struct ace_private *)dev->priv; + struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; /* @@ -1459,7 +1540,7 @@ static void ace_dump_trace(struct ace_private *ap) { #if 0 if (!ap->trace_buf) - if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL))); + if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL))) return; #endif } @@ -1664,7 +1745,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) { struct ace_private *ap; - ap = (struct ace_private *)dev->priv; + ap = dev->priv; while (evtcsm != evtprd) { switch (ap->evt_ring[evtcsm].evt) { @@ -1742,7 +1823,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) { - struct ace_private *ap = (struct ace_private *)dev->priv; + struct ace_private *ap = dev->priv; u32 idx; int mini_count = 0, std_count = 0; @@ -1795,7 +1876,8 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) skb = rip->skb; rip->skb = NULL; - pci_unmap_single(ap->pdev, rip->mapping, mapsize, PCI_DMA_FROMDEVICE); + pci_unmap_single(ap->pdev, rip->mapping, mapsize, + PCI_DMA_FROMDEVICE); skb_put(skb, retdesc->size); #if 0 /* unncessary */ @@ -1860,7 +1942,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) u32 txcsm, rxretcsm, rxretprd; u32 evtcsm, evtprd; - ap = (struct ace_private *)dev->priv; + ap = dev->priv; regs = ap->regs; /* @@ -1902,7 +1984,8 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) ap->stats.tx_packets++; ap->stats.tx_bytes += skb->len; - pci_unmap_single(ap->pdev, mapping, skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(ap->pdev, mapping, skb->len, + PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); ap->skb->tx_skbuff[idx].skb = NULL; @@ -1928,7 +2011,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) * Ie. skip the comparison of the tx producer vs. the * consumer. */ - if (ace_if_busy(dev) && xchg(&ap->tx_full, 0)) { + if (netif_queue_stopped(dev) && xchg(&ap->tx_full, 0)) { /* * This does not need to be atomic (and expensive), * I've seen cases where it would fail otherwise ;-( @@ -1959,7 +2042,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) * This has to go last in the interrupt handler and run with * the spin lock released ... what lock? */ - if (ace_if_running(dev)) { + if (netif_running(dev)) { int cur_size; int run_bh = 0; @@ -2108,7 +2191,7 @@ static int ace_close(struct net_device *dev) ace_if_down(dev); netif_stop_queue(dev); - ap = (struct ace_private *)dev->priv; + ap = dev->priv; regs = ap->regs; del_timer(&ap->timer); @@ -2143,7 +2226,8 @@ static int ace_close(struct net_device *dev) writel(0, &ap->tx_ring[i].addr.addrhi); writel(0, &ap->tx_ring[i].addr.addrlo); writel(0, &ap->tx_ring[i].flagsize); - pci_unmap_single(ap->pdev, mapping, skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(ap->pdev, mapping, skb->len, + PCI_DMA_TODEVICE); dev_kfree_skb(skb); ap->skb->tx_skbuff[i].skb = NULL; } @@ -2165,7 +2249,7 @@ static int ace_close(struct net_device *dev) static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ace_private *ap = (struct ace_private *)dev->priv; + struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; unsigned long addr; u32 idx, flagsize; @@ -2193,7 +2277,8 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) ap->skb->tx_skbuff[idx].skb = skb; ap->skb->tx_skbuff[idx].mapping = - pci_map_single(ap->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + pci_map_single(ap->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping; #if (BITS_PER_LONG == 64) writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi); @@ -2264,12 +2349,13 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu) ap->jumbo = 1; if (!test_and_set_bit(0, &ap->jumbo_refill_busy)) ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE); - ap->jumbo = 1; + ace_set_rxtx_parms(dev, 1); } } else { netif_stop_queue(dev); while (test_and_set_bit(0, &ap->jumbo_refill_busy)); synchronize_irq(); + ace_set_rxtx_parms(dev, 0); if (ap->jumbo){ struct cmd cmd; @@ -2287,7 +2373,7 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu) static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { #ifdef ETHTOOL - struct ace_private *ap = (struct ace_private *) dev->priv; + struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; struct ethtool_cmd ecmd; u32 link, speed; @@ -2429,7 +2515,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p) u16 *da; struct cmd cmd; - if(ace_if_running(dev)) + if(netif_running(dev)) return -EBUSY; memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); @@ -2587,7 +2673,7 @@ int __init ace_load_firmware(struct net_device *dev) struct ace_private *ap; struct ace_regs *regs; - ap = (struct ace_private *)dev->priv; + ap = dev->priv; regs = ap->regs; if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 7719338ab..958561a69 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -233,6 +233,7 @@ typedef struct { #define DMA_WRITE_MAX_128 0xa0 #define DMA_WRITE_MAX_256 0xc0 #define DMA_WRITE_MAX_1K 0xe0 +#define DMA_READ_WRITE_MASK 0xfc #define MEM_READ_MULTIPLE 0x00020000 #define PCI_66MHZ 0x00080000 #define PCI_32BIT 0x00100000 @@ -635,6 +636,7 @@ struct ace_private unsigned char *trace_buf; struct pci_dev *pdev; struct net_device *next; + int board_idx; u16 pci_command; u8 pci_latency; char name[48]; @@ -698,7 +700,7 @@ static inline void ace_set_txprd(struct ace_regs *regs, /* * Prototypes */ -static int ace_init(struct net_device *dev, int board_idx); +static int ace_init(struct net_device *dev); static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs); static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs); static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs); @@ -717,8 +719,10 @@ extern int ace_recycle(struct sk_buff *skb); #endif static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static int ace_set_mac_addr(struct net_device *dev, void *p); +static void ace_set_rxtx_parms(struct net_device *dev, int jumbo); static int ace_allocate_descriptors(struct net_device *dev); static void ace_free_descriptors(struct net_device *dev); +static void ace_init_cleanup(struct net_device *dev); static struct net_device_stats *ace_get_stats(struct net_device *dev); static int read_eeprom_byte(struct net_device *dev, unsigned long offset); diff --git a/drivers/net/aironet4500_core.c b/drivers/net/aironet4500_core.c index 205a43d97..36554e46f 100644 --- a/drivers/net/aironet4500_core.c +++ b/drivers/net/aironet4500_core.c @@ -18,6 +18,7 @@ */ #include <linux/module.h> +#include <linux/init.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/netdevice.h> @@ -2521,7 +2522,7 @@ static const char *aironet4500_core_version = struct net_device * aironet4500_devices[MAX_AWCS] = {NULL,NULL,NULL,NULL}; -static int awc_debug = 0; // 0xffffff; +int awc_debug = 0; // 0xffffff; static int p802_11_send = 0; // 1 static int awc_process_tx_results = 0; @@ -3197,9 +3198,7 @@ int awc_unregister_proc(void){ return 0; }; -#ifdef MODULE - -int init_module(void) +static int aironet_core_init(void) { // unsigned long flags; @@ -3210,11 +3209,12 @@ int init_module(void) } -void cleanup_module(void) +static void aironet_core_exit(void) { printk(KERN_INFO "aironet4500 unloading core module \n"); } - -#endif +module_init(aironet_core_init); +module_exit(aironet_core_exit); + diff --git a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c index b9da62ab7..cefa41b88 100644 --- a/drivers/net/aironet4500_proc.c +++ b/drivers/net/aironet4500_proc.c @@ -10,6 +10,7 @@ * */ #include <linux/module.h> +#include <linux/init.h> #include <linux/config.h> #include <linux/kernel.h> @@ -520,7 +521,7 @@ int awc_proc_unset_device(int device_number){ return 0; }; -int init_module(void) { +static int aironet_proc_init(void) { int i=0; AWC_ENTRY_EXIT_DEBUG("init_module"); @@ -539,7 +540,7 @@ int init_module(void) { }; -void cleanup_module(void){ +static void aironet_proc_exit(void){ int i=0; AWC_ENTRY_EXIT_DEBUG("cleanup_module"); @@ -552,4 +553,7 @@ void cleanup_module(void){ AWC_ENTRY_EXIT_DEBUG("exit"); }; -#endif // whole proc system styff
\ No newline at end of file +module_init(aironet_proc_init); +module_exit(aironet_proc_exit); + +#endif // whole proc system styff diff --git a/drivers/net/appletalk/Config.in b/drivers/net/appletalk/Config.in new file mode 100644 index 000000000..951cf498d --- /dev/null +++ b/drivers/net/appletalk/Config.in @@ -0,0 +1,20 @@ +# +# Appletalk driver configuration +# + +if [ "$CONFIG_ATALK" != "n" ]; then + mainmenu_option next_comment + comment 'Appletalk devices' + dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK + dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK + if [ "$CONFIG_COPS" != "n" ]; then + bool ' Dayna firmware support' CONFIG_COPS_DAYNA + bool ' Tangent firmware support' CONFIG_COPS_TANGENT + fi + dep_tristate 'Appletalk-IP driver support' CONFIG_IPDDP $CONFIG_ATALK + if [ "$CONFIG_IPDDP" != "n" ]; then + bool ' IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP + bool ' Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP + fi + endmenu +fi diff --git a/drivers/net/appletalk/Makefile b/drivers/net/appletalk/Makefile new file mode 100644 index 000000000..a59443c61 --- /dev/null +++ b/drivers/net/appletalk/Makefile @@ -0,0 +1,30 @@ +# +# Makefile for drivers/net/appletalk +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +obj-y := +obj-n := +obj-m := +obj- := +export-objs := + +obj-$(CONFIG_LTPC) += ltpc.o +obj-$(CONFIG_COPS) += cops.o +obj-$(CONFIG_IPDDP) += ipddp.o + +L_TARGET := appletalk.a +L_OBJS := $(filter-out $(export-objs), $(obj-y)) +LX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) + +include $(TOPDIR)/Rules.make + diff --git a/drivers/net/cops.c b/drivers/net/appletalk/cops.c index 466705f9e..466705f9e 100644 --- a/drivers/net/cops.c +++ b/drivers/net/appletalk/cops.c diff --git a/drivers/net/cops.h b/drivers/net/appletalk/cops.h index 438634912..438634912 100644 --- a/drivers/net/cops.h +++ b/drivers/net/appletalk/cops.h diff --git a/drivers/net/cops_ffdrv.h b/drivers/net/appletalk/cops_ffdrv.h index 3a20437b5..3a20437b5 100644 --- a/drivers/net/cops_ffdrv.h +++ b/drivers/net/appletalk/cops_ffdrv.h diff --git a/drivers/net/cops_ltdrv.h b/drivers/net/appletalk/cops_ltdrv.h index e3e850c31..e3e850c31 100644 --- a/drivers/net/cops_ltdrv.h +++ b/drivers/net/appletalk/cops_ltdrv.h diff --git a/drivers/net/ipddp.c b/drivers/net/appletalk/ipddp.c index a089ed9e2..a089ed9e2 100644 --- a/drivers/net/ipddp.c +++ b/drivers/net/appletalk/ipddp.c diff --git a/drivers/net/ipddp.h b/drivers/net/appletalk/ipddp.h index 0729a4d68..0729a4d68 100644 --- a/drivers/net/ipddp.h +++ b/drivers/net/appletalk/ipddp.h diff --git a/drivers/net/ltpc.c b/drivers/net/appletalk/ltpc.c index e461f8807..2728d63c0 100644 --- a/drivers/net/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -62,6 +62,9 @@ /*** * * $Log: ltpc.c,v $ + * Revision 1.1.2.1 2000/03/01 05:35:07 jgarzik + * at and tr cleanup + * * Revision 1.8 1997/01/28 05:44:54 bradford * Clean up for non-module a little. * Hacked about a bit to clean things up - Alan Cox diff --git a/drivers/net/ltpc.h b/drivers/net/appletalk/ltpc.h index cd30544a3..cd30544a3 100644 --- a/drivers/net/ltpc.h +++ b/drivers/net/appletalk/ltpc.h diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 01dd799b3..5ef42cf9c 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1,4 +1,7 @@ -/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */ +/* cs89x0.c: A Crystal Semiconductor (Now Cirrus Logic) CS89[02]0 + * driver for linux. + */ + /* Written 1996 by Russell Nelson, with reference to skeleton.c written 1993-1994 by Donald Becker. @@ -6,8 +9,8 @@ This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. - The author may be reached at nelson@crynwr.com, Crynwr - Software, 11 Grant St., Potsdam, NY 13676 + The author may be reached at nelson@crynwr.com, Crynwr + Software, 521 Pleasant Valley Rd., Potsdam, NY 13676 Changelog: @@ -25,19 +28,30 @@ : as an example. Disabled autoprobing in init_module(), : not a good thing to do to other devices while Linux : is running from all accounts. - + + Russ Nelson : Jul 13 1998. Added RxOnly DMA support. + + Melody Lee : Aug 10 1999. Changes for Linux 2.2.5 compatibility. + : email: ethernet@crystal.cirrus.com + Alan Cox : Removed 1.2 support, added 2.1 extra counters. + + Andrew Morton : andrewm@uow.edu.au + : Kernel 2.3.48 + : Handle kmalloc() failures + : Other resource allocation fixes + : Add SMP locks + : Integrate Russ Nelson's ALLOW_DMA functionality back in. + : If ALLOW_DMA is true, make DMA runtime selectable + : Folded in changes from Cirrus (Melody Lee + : <klee@crystal.cirrus.com>) + : Don't call netif_wake_queue() in net_send_packet() + : Fixed an out-of-mem bug in dma_rx() + : Updated Documentation/cs89x0.txt */ static char *version = -"cs89x0.c:v1.03 11/26/96 Russell Nelson <nelson@crynwr.com>\n"; - -/* ======================= configure the driver here ======================= */ - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif +"cs89x0.c: (kernel 2.3.48) Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n"; /* ======================= end of configuration ======================= */ @@ -52,7 +66,19 @@ static char *version = #define MOD_DEC_USE_COUNT #endif -#define PRINTK(x) printk x +/* + * Set this to zero to disable DMA code + * + * Note that even if DMA is turned off we still support the 'dma' and 'use_dma' + * module options so we don't break any startup scripts. + */ +#define ALLOW_DMA 1 + +/* + * Set this to zero to remove all the debug statements via + * dead code elimination + */ +#define DEBUGGING 0 /* Sources: @@ -76,39 +102,66 @@ static char *version = #include <asm/system.h> #include <asm/bitops.h> #include <asm/io.h> +#if ALLOW_DMA +#include <asm/dma.h> +#endif #include <linux/errno.h> #include <linux/init.h> +#include <linux/spinlock.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> + #include "cs89x0.h" /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int netcard_portlist[] __initdata = - { 0x300, 0x320, 0x340, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; + { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0}; -static unsigned int net_debug = NET_DEBUG; +#if DEBUGGING +static unsigned int net_debug = 5; +#else +#define net_debug 0 /* gcc will remove all the debug code for us */ +#endif /* The number of low I/O ports used by the ethercard. */ #define NETCARD_IO_EXTENT 16 +/* we allow the user to override various values normally set in the EEPROM */ +#define FORCE_RJ45 0x0001 /* pick one of these three */ +#define FORCE_AUI 0x0002 +#define FORCE_BNC 0x0004 + +#define FORCE_AUTO 0x0010 /* pick one of these three */ +#define FORCE_HALF 0x0020 +#define FORCE_FULL 0x0030 + /* Information that need to be kept for each board. */ struct net_local { struct net_device_stats stats; int chip_type; /* one of: CS8900, CS8920, CS8920M */ char chip_revision; /* revision letter of the chip ('A'...) */ - int send_cmd; /* the propercommand used to send a packet. */ - int auto_neg_cnf; - int adapter_cnf; - int isa_config; - int irq_map; - int rx_mode; - int curr_rx_cfg; - int linectl; - int send_underrun; /* keep track of how many underruns in a row we get */ - struct sk_buff *skb; + int send_cmd; /* the proper send command: TX_NOW, TX_AFTER_381, or TX_AFTER_ALL */ + int auto_neg_cnf; /* auto-negotiation word from EEPROM */ + int adapter_cnf; /* adapter configuration from EEPROM */ + int isa_config; /* ISA configuration from EEPROM */ + int irq_map; /* IRQ map from EEPROM */ + int rx_mode; /* what mode are we in? 0, RX_MULTCAST_ACCEPT, or RX_ALL_ACCEPT */ + int curr_rx_cfg; /* a copy of PP_RxCFG */ + int linectl; /* either 0 or LOW_RX_SQUELCH, depending on configuration. */ + int send_underrun; /* keep track of how many underruns in a row we get */ + int force; /* force various values; see FORCE* above. */ + spinlock_t lock; +#if ALLOW_DMA + int use_dma; /* Flag: we're using dma */ + int dma; /* DMA channel */ + int dmasize; /* 16 or 64 */ + unsigned char *dma_buff; /* points to the beginning of the buffer */ + unsigned char *end_dma_buff; /* points to the end of the buffer */ + unsigned char *rx_dma_ptr; /* points to the next packet */ +#endif }; /* Index to functions, as function prototypes. */ @@ -117,7 +170,7 @@ extern int cs89x0_probe(struct net_device *dev); static int cs89x0_probe1(struct net_device *dev, int ioaddr); static int net_open(struct net_device *dev); -static int net_send_packet(struct sk_buff *skb, struct net_device *dev); +static int net_send_packet(struct sk_buff *skb, struct net_device *dev); static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void set_multicast_list(struct net_device *dev); static void net_timeout(struct net_device *dev); @@ -128,7 +181,11 @@ static void reset_chip(struct net_device *dev); static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer); static int get_eeprom_cksum(int off, int len, int *buffer); static int set_mac_address(struct net_device *dev, void *addr); - +static void count_rx_errors(int status, struct net_local *lp); +#if ALLOW_DMA +static void get_dma_channel(struct net_device *dev); +static void release_dma_buff(struct net_local *lp); +#endif /* Example routines you must write ;->. */ #define tx_done(dev) 1 @@ -139,6 +196,7 @@ static int set_mac_address(struct net_device *dev, void *addr); If dev->base_addr == 1, always return failure. If dev->base_addr == 2, allocate space for the device and return success (detachable devices only). + Return 0 on success. */ int __init cs89x0_probe(struct net_device *dev) @@ -146,6 +204,9 @@ int __init cs89x0_probe(struct net_device *dev) int i; int base_addr = dev ? dev->base_addr : 0; + if (net_debug) + printk("cs89x0:cs89x0_probe()\n"); + if (base_addr > 0x1ff) /* Check a single specified location. */ return cs89x0_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ @@ -158,34 +219,38 @@ int __init cs89x0_probe(struct net_device *dev) if (cs89x0_probe1(dev, ioaddr) == 0) return 0; } - printk("cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); + printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); return ENODEV; } -extern int inline readreg(struct net_device *dev, int portno) +extern int inline +readreg(struct net_device *dev, int portno) { outw(portno, dev->base_addr + ADD_PORT); return inw(dev->base_addr + DATA_PORT); } -extern void inline writereg(struct net_device *dev, int portno, int value) +extern void inline +writereg(struct net_device *dev, int portno, int value) { outw(portno, dev->base_addr + ADD_PORT); outw(value, dev->base_addr + DATA_PORT); } - -extern int inline readword(struct net_device *dev, int portno) +extern int inline +readword(struct net_device *dev, int portno) { return inw(dev->base_addr + portno); } -extern void inline writeword(struct net_device *dev, int portno, int value) +extern void inline +writeword(struct net_device *dev, int portno, int value) { outw(value, dev->base_addr + portno); } -static int __init wait_eeprom_ready(struct net_device *dev) +static int __init +wait_eeprom_ready(struct net_device *dev) { int timeout = jiffies; /* check to see if the EEPROM is ready, a timeout is used - @@ -197,7 +262,8 @@ static int __init wait_eeprom_ready(struct net_device *dev) return 0; } -static int __init get_eeprom_data(struct net_device *dev, int off, int len, int *buffer) +static int __init +get_eeprom_data(struct net_device *dev, int off, int len, int *buffer) { int i; @@ -214,7 +280,8 @@ static int __init get_eeprom_data(struct net_device *dev, int off, int len, int return 0; } -static int __init get_eeprom_cksum(int off, int len, int *buffer) +static int __init +get_eeprom_cksum(int off, int len, int *buffer) { int i, cksum; @@ -229,19 +296,28 @@ static int __init get_eeprom_cksum(int off, int len, int *buffer) /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probes avoids doing writes, and - verifies that the correct device exists and functions. */ + verifies that the correct device exists and functions. + Return 0 on success. + */ -static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) +static int __init +cs89x0_probe1(struct net_device *dev, int ioaddr) { struct net_local *lp; static unsigned version_printed = 0; int i; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; + int retval; /* Initialize the device structure. */ if (dev->priv == NULL) { dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); + if (dev->priv == 0) + { + retval = ENOMEM; + goto out; + } memset(dev->priv, 0, sizeof(struct net_local)); } lp = (struct net_local *)dev->priv; @@ -257,7 +333,10 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) } if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) - return ENODEV; + { + retval = ENODEV; + goto out1; + } /* Fill in the 'dev' fields. */ dev->base_addr = ioaddr; @@ -278,7 +357,7 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) if (net_debug && version_printed++ == 0) printk(version); - printk("%s: cs89%c0%s rev %c found at %#3lx", + printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#3lx ", dev->name, lp->chip_type==CS8900?'0':'2', lp->chip_type==CS8920M?"M":"", @@ -289,11 +368,11 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) /* First check to see if an EEPROM is attached*/ if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0) - printk("\ncs89x0: No EEPROM, relying on command line....\n"); + printk(KERN_WARNING "\ncs89x0: No EEPROM, relying on command line....\n"); else if (get_eeprom_data(dev, START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) { - printk("\ncs89x0: EEPROM read failed, relying on command line.\n"); + printk(KERN_WARNING "\ncs89x0: EEPROM read failed, relying on command line.\n"); } else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) { - printk("\ncs89x0: EEPROM checksum bad, relying on command line\n"); + printk(KERN_WARNING "\ncs89x0: EEPROM checksum bad, relying on command line\n"); } else { /* get transmission control word but keep the autonegotiation bits */ if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2]; @@ -301,16 +380,36 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) if (!lp->adapter_cnf) lp->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2]; /* Store ISA configuration */ lp->isa_config = eeprom_buff[ISA_CNF_OFFSET/2]; - /* store the initial memory base address */ dev->mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8; + + /* eeprom_buff has 32-bit ints, so we can't just memcpy it */ + /* store the initial memory base address */ for (i = 0; i < ETH_ALEN/2; i++) { dev->dev_addr[i*2] = eeprom_buff[i]; dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8; } } + /* allow them to force multiple transceivers. If they force multiple, autosense */ + { + int count = 0; + if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; } + if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_AUI; count++; } + if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; } + if (count > 1) {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; } + else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; } + else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; } + else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; } + } + + /* FIXME: We don't let you set dc-dc polarity or low RX squelch from the command line: add it here */ - printk(" media %s%s%s", + /* FIXME: We don't let you set the IMM bit from the command line: add it to lp->auto_neg_cnf here */ + + /* FIXME: we don't set the Ethernet address on the command line. Use + ifconfig IFACE hw ether AABBCCDDEEFF */ + + printk(KERN_INFO "cs89x0 media %s%s%s", (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"", (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"", (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":""); @@ -353,14 +452,33 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) dev->irq = i; } - printk(" IRQ %d", dev->irq); + printk(", IRQ %d", dev->irq); +#if ALLOW_DMA + if (lp->use_dma) + { + get_dma_channel(dev); + printk(", DMA %d", dev->dma); + } + else +#endif + { + printk(", programmed I/O"); + } /* print the ethernet address. */ + printk(", MAC "); for (i = 0; i < ETH_ALEN; i++) - printk(" %2.2x", dev->dev_addr[i]); + { + printk("%s%02x", i ? ":" : "", dev->dev_addr[i]); + } /* Grab the region so we can find another board if autoIRQ fails. */ + + /* + * FIXME: we should check this, but really the isapnp stuff should have given + * us a free region. Sort this out when the isapnp is sorted out + */ request_region(ioaddr, NETCARD_IO_EXTENT,"cs89x0"); dev->open = net_open; @@ -376,11 +494,188 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr) ether_setup(dev); printk("\n"); + if (net_debug) + printk("cs89x0_probe1() successful\n"); return 0; +out1: + kfree(dev->priv); + dev->priv = 0; +out: + return retval; +} + + +/********************************* + * This page contains DMA routines +**********************************/ + +#if ALLOW_DMA + +#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17) + +static void +get_dma_channel(struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + + if (lp->dma) { + dev->dma = lp->dma; + lp->isa_config |= ISA_RxDMA; + } else { + if ((lp->isa_config & ANY_ISA_DMA) == 0) + return; + dev->dma = lp->isa_config & DMA_NO_MASK; + if (lp->chip_type == CS8900) + dev->dma += 5; + if (dev->dma < 5 || dev->dma > 7) { + lp->isa_config &= ~ANY_ISA_DMA; + return; + } + } + return; +} + +static void +write_dma(struct net_device *dev, int chip_type, int dma) +{ + struct net_local *lp = (struct net_local *)dev->priv; + if ((lp->isa_config & ANY_ISA_DMA) == 0) + return; + if (chip_type == CS8900) { + writereg(dev, PP_CS8900_ISADMA, dma-5); + } else { + writereg(dev, PP_CS8920_ISADMA, dma); + } +} + +static void +set_dma_cfg(struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + + if (lp->use_dma) + { + if ((lp->isa_config & ANY_ISA_DMA) == 0) + { + if (net_debug > 3) + printk("set_dma_cfg(): no DMA\n"); + return; + } + if (lp->isa_config & ISA_RxDMA) + { + lp->curr_rx_cfg |= RX_DMA_ONLY; + if (net_debug > 3) + printk("set_dma_cfg(): RX_DMA_ONLY\n"); + } + else + { + lp->curr_rx_cfg |= AUTO_RX_DMA; /* not that we support it... */ + if (net_debug > 3) + printk("set_dma_cfg(): AUTO_RX_DMA\n"); + } + } +} + +static int +dma_bufcfg(struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + if (lp->use_dma) + return (lp->isa_config & ANY_ISA_DMA)? RX_DMA_ENBL : 0; + else + return 0; +} + +static int +dma_busctl(struct net_device *dev) +{ + int retval = 0; + struct net_local *lp = (struct net_local *)dev->priv; + if (lp->use_dma) + { + if (lp->isa_config & ANY_ISA_DMA) + retval |= RESET_RX_DMA; /* Reset the DMA pointer */ + if (lp->isa_config & DMA_BURST) + retval |= DMA_BURST_MODE; /* Does ISA config specify DMA burst ? */ + if (lp->dmasize == 64) + retval |= RX_DMA_SIZE_64K; /* did they ask for 64K? */ + retval |= MEMORY_ON; /* we need memory enabled to use DMA. */ + } + return retval; +} + +static void +dma_rx(struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + struct sk_buff *skb; + int status, length; + unsigned char *bp = lp->rx_dma_ptr; + + { + int i; + for (i = 0; i < 1000; i++) + ; + } + + status = bp[0] + (bp[1]<<8); + length = bp[2] + (bp[3]<<8); + bp += 4; + if (net_debug > 5) + { + printk( "%s: receiving DMA packet at %lx, status %x, length %x\n", + dev->name, (unsigned long)bp, status, length); + } + if ((status & RX_OK) == 0) { + count_rx_errors(status, lp); + goto skip_this_frame; + } + + /* Malloc up new buffer. */ + skb = alloc_skb(length, GFP_ATOMIC); + if (skb == NULL) { + if (net_debug) /* I don't think we want to do this to a stressed system */ + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + lp->stats.rx_dropped++; + + /* AKPM: advance bp to the next frame */ +skip_this_frame: + bp += (length + 3) & ~3; + if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024; + lp->rx_dma_ptr = bp; + return; + } + + skb->len = length; + skb->dev = dev; + + if (bp + length > lp->end_dma_buff) { + int semi_cnt = lp->end_dma_buff - bp; + memcpy(skb_put(skb,semi_cnt), bp, semi_cnt); + memcpy(skb_put(skb,length - semi_cnt), lp->dma_buff, + length - semi_cnt); + } else { + memcpy(skb_put(skb,length), bp, length); + } + bp += (length + 3) & ~3; + if (bp >= lp->end_dma_buff) bp -= lp->dmasize*1024; + lp->rx_dma_ptr = bp; + + if (net_debug > 3) + { + printk( "%s: received %d byte DMA packet of type %x\n", + dev->name, length, + (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); + } + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + lp->stats.rx_packets++; + return; } -void __init -reset_chip(struct net_device *dev) +#endif /* ALLOW_DMA */ + +void __init reset_chip(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; @@ -399,8 +694,8 @@ reset_chip(struct net_device *dev) outb(0, ioaddr + DATA_PORT + 1); outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT); - outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT); - outb((dev->mem_start >> 24) & 0xff, ioaddr + DATA_PORT + 1); + outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); + outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); } /* Wait until the chip is reset */ reset_start_time = jiffies; @@ -430,11 +725,18 @@ control_dc_dc(struct net_device *dev, int on_not_off) } +#define DETECTED_NONE 0 +#define DETECTED_RJ45H 1 +#define DETECTED_RJ45F 2 +#define DETECTED_AUI 3 +#define DETECTED_BNC 4 + static int detect_tp(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int timenow = jiffies; + int fdx; if (net_debug > 1) printk("%s: Attempting TP\n", dev->name); @@ -450,35 +752,63 @@ detect_tp(struct net_device *dev) for (timenow = jiffies; jiffies - timenow < 15; ) ; if ((readreg(dev, PP_LineST) & LINK_OK) == 0) - return 0; - - if (lp->chip_type != CS8900) { + return DETECTED_NONE; + + if (lp->chip_type == CS8900) { + switch (lp->force & 0xf0) { +#if 0 + case FORCE_AUTO: + printk("%s: cs8900 doesn't autonegotiate\n",dev->name); + return DETECTED_NONE; +#endif + /* CS8900 doesn't support AUTO, change to HALF*/ + case FORCE_AUTO: + lp->force &= ~FORCE_AUTO; + lp->force |= FORCE_HALF; + break; + case FORCE_HALF: + break; + case FORCE_FULL: + writereg(dev, PP_TestCTL, readreg(dev, PP_TestCTL) | FDX_8900); + break; + } + fdx = readreg(dev, PP_TestCTL) & FDX_8900; + } else { + switch (lp->force & 0xf0) { + case FORCE_AUTO: + lp->auto_neg_cnf = AUTO_NEG_ENABLE; + break; + case FORCE_HALF: + lp->auto_neg_cnf = 0; + break; + case FORCE_FULL: + lp->auto_neg_cnf = RE_NEG_NOW | ALLOW_FDX; + break; + } writereg(dev, PP_AutoNegCTL, lp->auto_neg_cnf & AUTO_NEG_MASK); if ((lp->auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) { - printk("%s: negotiating duplex...\n",dev->name); + printk(KERN_INFO "%s: negotiating duplex...\n",dev->name); while (readreg(dev, PP_AutoNegST) & AUTO_NEG_BUSY) { if (jiffies - timenow > 4000) { - printk("**** Full / half duplex auto-negotiation timed out ****\n"); + printk(KERN_ERR "**** Full / half duplex auto-negotiation timed out ****\n"); break; } } } - if (readreg(dev, PP_AutoNegST) & FDX_ACTIVE) - printk("%s: using full duplex\n", dev->name); - else - printk("%s: using half duplex\n", dev->name); + fdx = readreg(dev, PP_AutoNegST) & FDX_ACTIVE; } - - return A_CNF_MEDIA_10B_T; + if (fdx) + return DETECTED_RJ45F; + else + return DETECTED_RJ45H; } /* send a test packet - return true if carrier bits are ok */ static int send_test_pkt(struct net_device *dev) { - int ioaddr = dev->base_addr; char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 0, 46, /* A 46 in network order */ 0, 0, /* DSAP=0 & SSAP=0 fields */ @@ -490,8 +820,8 @@ send_test_pkt(struct net_device *dev) memcpy(test_packet, dev->dev_addr, ETH_ALEN); memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); - outw(TX_AFTER_ALL, ioaddr + TX_CMD_PORT); - outw(ETH_ZLEN, ioaddr + TX_LEN_PORT); + writeword(dev, TX_CMD_PORT, TX_AFTER_ALL); + writeword(dev, TX_LEN_PORT, ETH_ZLEN); /* Test to see if the chip has allocated memory for the packet */ while (jiffies - timenow < 5) @@ -501,11 +831,7 @@ send_test_pkt(struct net_device *dev) return 0; /* this shouldn't happen */ /* Write the contents of the packet */ - if (dev->mem_start) { - memcpy((void *)dev->mem_start + PP_TxFrame, test_packet, ETH_ZLEN); - } else { - outsw(ioaddr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); - } + outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); if (net_debug > 1) printk("Sending test packet "); /* wait a couple of jiffies for packet to be received */ @@ -531,9 +857,9 @@ detect_aui(struct net_device *dev) writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY); if (send_test_pkt(dev)) - return A_CNF_MEDIA_AUI; + return DETECTED_AUI; else - return 0; + return DETECTED_NONE; } static int @@ -547,9 +873,9 @@ detect_bnc(struct net_device *dev) writereg(dev, PP_LineCTL, (lp->linectl &~ AUTO_AUI_10BASET) | AUI_ONLY); if (send_test_pkt(dev)) - return A_CNF_MEDIA_10B_2; + return DETECTED_BNC; else - return 0; + return DETECTED_NONE; } @@ -579,6 +905,9 @@ write_irq(struct net_device *dev, int chip_type, int irq) registers that "should" only need to be set once at boot, so that there is non-reboot way to recover if something goes wrong. */ + +/* AKPM: do we need to do any locking here? */ + static int net_open(struct net_device *dev) { @@ -588,9 +917,15 @@ net_open(struct net_device *dev) if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ +/* Cirrus' release had this: */ +#if 0 + writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ ); +#endif +/* And 2.3.47 had this: */ writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); + for (i = 2; i < CS8920_NO_INTS; i++) if ((1 << dev->irq) & lp->irq_map) { - if (request_irq (i, NULL, 0, "cs8920", dev) != -EBUSY) { + if (request_irq (i, NULL, 0, "cs89x0", dev) != -EBUSY) { write_irq(dev, lp->chip_type, i); writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); if (request_irq (dev->irq = i, &net_interrupt, 0, "cs89x0", dev) == 0) @@ -601,21 +936,74 @@ net_open(struct net_device *dev) if (i >= CS8920_NO_INTS) { writereg(dev, PP_BusCTL, 0); /* disable interrupts. */ + if (net_debug) + printk("cs89x0: can't get an interrupt\n"); return -EAGAIN; } } else { if (((1 << dev->irq) & lp->irq_map) == 0) { - printk("%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", + printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", dev->name, dev->irq, lp->irq_map); return -EAGAIN; } +/* FIXME: Cirrus' release had this: */ + writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ ); +/* And 2.3.47 had this: */ +#if 0 writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); +#endif write_irq(dev, lp->chip_type, dev->irq); if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) { + if (net_debug) + printk("cs89x0: request_irq(%d) failed\n", dev->irq); return -EAGAIN; } } +#if ALLOW_DMA + if (lp->use_dma) + { + if (lp->isa_config & ANY_ISA_DMA) { + unsigned long flags; + lp->dma_buff = (unsigned char *)__get_dma_pages(GFP_KERNEL, + (lp->dmasize * 1024) / PAGE_SIZE); + + if (!lp->dma_buff) { + printk(KERN_ERR "%s: cannot get %dK memory for DMA\n", dev->name, lp->dmasize); + goto release_irq; + } + if (net_debug > 1) + { + printk( "%s: dma %lx %lx\n", + dev->name, + (unsigned long)lp->dma_buff, + (unsigned long)virt_to_bus(lp->dma_buff)); + } + if ((unsigned long)virt_to_bus(lp->dma_buff) >= MAX_DMA_ADDRESS || + !dma_page_eq(lp->dma_buff, lp->dma_buff+lp->dmasize*1024-1)) { + printk(KERN_ERR "%s: not usable as DMA buffer\n", dev->name); + goto release_irq; + } + memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */ + if (request_dma(dev->dma, "cs89x0")) { + printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma); + goto release_irq; + } + write_dma(dev, lp->chip_type, dev->dma); + lp->rx_dma_ptr = lp->dma_buff; + lp->end_dma_buff = lp->dma_buff + lp->dmasize*1024; + spin_lock_irqsave(&lp->lock, flags); + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + set_dma_mode(dev->dma, 0x14); /* auto_init as well */ + set_dma_addr(dev->dma, virt_to_bus(lp->dma_buff)); + set_dma_count(dev->dma, lp->dmasize*1024); + enable_dma(dev->dma); + spin_unlock_irqrestore(&lp->lock, flags); + } + } +#endif /* ALLOW_DMA */ + /* set the Ethernet address */ for (i=0; i < ETH_ALEN/2; i++) writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8)); @@ -637,8 +1025,11 @@ net_open(struct net_device *dev) default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); } if (!result) { - printk("%s: EEPROM is configured for unavailable media\n", dev->name); + printk(KERN_ERR "%s: EEPROM is configured for unavailable media\n", dev->name); release_irq: +#if ALLOW_DMA + release_dma_buff(lp); +#endif writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON)); free_irq(dev->irq, dev); return -EAGAIN; @@ -648,43 +1039,58 @@ net_open(struct net_device *dev) switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) { case A_CNF_MEDIA_10B_T: result = detect_tp(dev); - if (!result) printk("%s: 10Base-T (RJ-45) has no cable\n", dev->name); - if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ - result = A_CNF_MEDIA_10B_T; /* Yes! I don't care if I see a link pulse */ + if (result==DETECTED_NONE) { + printk(KERN_WARNING "%s: 10Base-T (RJ-45) has no cable\n", dev->name); + if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ + result = DETECTED_RJ45H; /* Yes! I don't care if I see a link pulse */ + } break; case A_CNF_MEDIA_AUI: result = detect_aui(dev); - if (!result) printk("%s: 10Base-5 (AUI) has no cable\n", dev->name); - if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ - result = A_CNF_MEDIA_AUI; /* Yes! I don't care if I see a carrrier */ + if (result==DETECTED_NONE) { + printk(KERN_WARNING "%s: 10Base-5 (AUI) has no cable\n", dev->name); + if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ + result = DETECTED_AUI; /* Yes! I don't care if I see a carrrier */ + } break; case A_CNF_MEDIA_10B_2: result = detect_bnc(dev); - if (!result) printk("%s: 10Base-2 (BNC) has no cable\n", dev->name); - if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ - result = A_CNF_MEDIA_10B_2; /* Yes! I don't care if I can xmit a packet */ + if (result==DETECTED_NONE) { + printk(KERN_WARNING "%s: 10Base-2 (BNC) has no cable\n", dev->name); + if (lp->auto_neg_cnf & IMM_BIT) /* check "ignore missing media" bit */ + result = DETECTED_BNC; /* Yes! I don't care if I can xmit a packet */ + } break; case A_CNF_MEDIA_AUTO: writereg(dev, PP_LineCTL, lp->linectl | AUTO_AUI_10BASET); if (lp->adapter_cnf & A_CNF_10B_T) - if ((result = detect_tp(dev)) != 0) + if ((result = detect_tp(dev)) != DETECTED_NONE) break; if (lp->adapter_cnf & A_CNF_AUI) - if ((result = detect_aui(dev)) != 0) + if ((result = detect_aui(dev)) != DETECTED_NONE) break; if (lp->adapter_cnf & A_CNF_10B_2) - if ((result = detect_bnc(dev)) != 0) + if ((result = detect_bnc(dev)) != DETECTED_NONE) break; - printk("%s: no media detected\n", dev->name); + printk(KERN_ERR "%s: no media detected\n", dev->name); goto release_irq; } switch(result) { - case 0: printk("%s: no network cable attached to configured media\n", dev->name); + case DETECTED_NONE: + printk(KERN_ERR "%s: no network cable attached to configured media\n", dev->name); goto release_irq; - case A_CNF_MEDIA_10B_T: printk("%s: using 10Base-T (RJ-45)\n", dev->name);break; - case A_CNF_MEDIA_AUI: printk("%s: using 10Base-5 (AUI)\n", dev->name);break; - case A_CNF_MEDIA_10B_2: printk("%s: using 10Base-2 (BNC)\n", dev->name);break; - default: printk("%s: unexpected result was %x\n", dev->name, result); goto release_irq; + case DETECTED_RJ45H: + printk(KERN_INFO "%s: using half-duplex 10Base-T (RJ-45)\n", dev->name); + break; + case DETECTED_RJ45F: + printk(KERN_INFO "%s: using full-duplex 10Base-T (RJ-45)\n", dev->name); + break; + case DETECTED_AUI: + printk(KERN_INFO "%s: using 10Base-5 (AUI)\n", dev->name); + break; + case DETECTED_BNC: + printk(KERN_INFO "%s: using 10Base-2 (BNC)\n", dev->name); + break; } /* Turn on both receive and transmit operations */ @@ -695,22 +1101,34 @@ net_open(struct net_device *dev) writereg(dev, PP_RxCTL, DEF_RX_ACCEPT); lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL; + if (lp->isa_config & STREAM_TRANSFER) lp->curr_rx_cfg |= RX_STREAM_ENBL; - +#if ALLOW_DMA + set_dma_cfg(dev); +#endif writereg(dev, PP_RxCFG, lp->curr_rx_cfg); writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL | - TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); + TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL | - TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); +#if ALLOW_DMA + dma_bufcfg(dev) | +#endif + TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); /* now that we've got our act together, enable everything */ writereg(dev, PP_BusCTL, ENABLE_IRQ + | (dev->mem_start?MEMORY_ON : 0) /* turn memory on */ +#if ALLOW_DMA + | dma_busctl(dev) +#endif ); MOD_INC_USE_COUNT; netif_start_queue(dev); + if (net_debug) + printk("cs89x0: net_open() succeeded\n"); return 0; } @@ -727,39 +1145,54 @@ static void net_timeout(struct net_device *dev) static int net_send_packet(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; - short ioaddr = dev->base_addr; - unsigned long flags; if (net_debug > 3) - printk("%s: sent %d byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); + { + printk("%s: sent %d byte packet of type %x\n", + dev->name, skb->len, + (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); + } /* keep the upload from being interrupted, since we ask the chip to start transmitting before the whole packet has been completely uploaded. */ - save_flags(flags); - cli(); + spin_lock_irq(&lp->lock); netif_stop_queue(dev); - + /* initiate a transmit sequence */ - outw(lp->send_cmd, ioaddr + TX_CMD_PORT); - outw(skb->len, ioaddr + TX_LEN_PORT); + writeword(dev, TX_CMD_PORT, lp->send_cmd); + writeword(dev, TX_LEN_PORT, skb->len); /* Test to see if the chip has allocated memory for the packet */ - if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { - /* Gasp! It hasn't. But that shouldn't happen since - we're waiting for TxOk, so return 1 and requeue this packet. */ - restore_flags(flags); + if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) + { + /* + * Gasp! It hasn't. But that shouldn't happen since + * we're waiting for TxOk, so return 1 and requeue this packet. + */ + + spin_unlock_irq(&lp->lock); + if (net_debug) printk("cs89x0: Tx buffer not free!\n"); return 1; } /* Write the contents of the packet */ - outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); - - restore_flags(flags); + outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); + spin_unlock_irq(&lp->lock); dev->trans_start = jiffies; dev_kfree_skb (skb); - netif_wake_queue(dev); - + + /* + * We DO NOT call netif_wake_queue() here. + * We also DO NOT call netif_start_queue(). + * + * Either of these would cause another bottom half run through + * net_send_packet() before this packet has fully gone out. That causes + * us to hit the "Gasp!" above and the send is rescheduled. it runs like + * a dog. We just return and wait for the Tx completion interrupt handler + * to restart the netdevice layer + */ + return 0; } @@ -771,7 +1204,7 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs) struct net_device *dev = dev_id; struct net_local *lp; int ioaddr, status; - + ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; @@ -792,11 +1225,18 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs) case ISQ_TRANSMITTER_EVENT: lp->stats.tx_packets++; netif_wake_queue(dev); /* Inform upper layers. */ - if ((status & TX_OK) == 0) lp->stats.tx_errors++; - if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; - if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; - if (status & TX_LATE_COL) lp->stats.tx_window_errors++; - if (status & TX_16_COL) lp->stats.tx_aborted_errors++; + if ((status & ( TX_OK | + TX_LOST_CRS | + TX_SQE_ERROR | + TX_LATE_COL | + TX_16_COL)) != TX_OK) + { + if ((status & TX_OK) == 0) lp->stats.tx_errors++; + if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; + if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; + if (status & TX_LATE_COL) lp->stats.tx_window_errors++; + if (status & TX_16_COL) lp->stats.tx_aborted_errors++; + } break; case ISQ_BUFFER_EVENT: if (status & READY_FOR_TX) { @@ -819,6 +1259,22 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs) event of a tx underrun */ netif_wake_queue(dev); /* Inform upper layers. */ } +#if ALLOW_DMA + if (lp->use_dma && (status & RX_DMA)) { + int count = readreg(dev, PP_DmaFrameCnt); + while(count) { + if (net_debug > 5) + printk("%s: receiving %d DMA frames\n", dev->name, count); + if (net_debug > 2 && count >1) + printk("%s: receiving %d DMA frames\n", dev->name, count); + dma_rx(dev); + if (--count == 0) + count = readreg(dev, PP_DmaFrameCnt); + if (net_debug > 2 && count > 0) + printk("%s: continuing with %d DMA frames\n", dev->name, count); + } + } +#endif break; case ISQ_RX_MISS_EVENT: lp->stats.rx_missed_errors += (status >>6); @@ -830,45 +1286,58 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs) } } +static void +count_rx_errors(int status, struct net_local *lp) +{ + lp->stats.rx_errors++; + if (status & RX_RUNT) lp->stats.rx_length_errors++; + if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++; + if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT))) + /* per str 172 */ + lp->stats.rx_crc_errors++; + if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++; + return; +} + /* We have a good packet(s), get it/them out of the buffers. */ static void net_rx(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; - int ioaddr = dev->base_addr; struct sk_buff *skb; int status, length; + int ioaddr = dev->base_addr; status = inw(ioaddr + RX_FRAME_PORT); length = inw(ioaddr + RX_FRAME_PORT); + if ((status & RX_OK) == 0) { - lp->stats.rx_errors++; - if (status & RX_RUNT) lp->stats.rx_length_errors++; - if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++; - if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT))) - /* per str 172 */ - lp->stats.rx_crc_errors++; - if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++; + count_rx_errors(status, lp); return; } /* Malloc up new buffer. */ skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); +#if 0 /* Again, this seems a cruel thing to do */ + printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); +#endif lp->stats.rx_dropped++; return; } skb->len = length; skb->dev = dev; - insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1); + insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1); if (length & 1) skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT); - if (net_debug > 3)printk("%s: received %d byte packet of type %x\n", - dev->name, length, - (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); + if (net_debug > 3) + { + printk( "%s: received %d byte packet of type %x\n", + dev->name, length, + (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); + } skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); @@ -877,10 +1346,23 @@ net_rx(struct net_device *dev) return; } +#if ALLOW_DMA +static void release_dma_buff(struct net_local *lp) +{ + if (lp->dma_buff) + { + free_pages((unsigned long)(lp->dma_buff), (lp->dmasize * 1024) / PAGE_SIZE); + lp->dma_buff = 0; + } +} +#endif + /* The inverse routine to net_open(). */ static int net_close(struct net_device *dev) { + struct net_local *lp = (struct net_local *)dev->priv; + netif_stop_queue(dev); writereg(dev, PP_RxCFG, 0); @@ -890,11 +1372,16 @@ net_close(struct net_device *dev) free_irq(dev->irq, dev); - /* Update the statistics here. */ +#if ALLOW_DMA + if (lp->use_dma && lp->dma) { + free_dma(dev->dma); + release_dma_buff(lp); + } +#endif + /* Update the statistics here. */ MOD_DEC_USE_COUNT; return 0; - } /* Get the current statistics. This may be called with the card open or @@ -903,12 +1390,13 @@ static struct net_device_stats * net_get_stats(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; + unsigned long flags; - cli(); + spin_lock_irqsave(&lp->lock, flags); /* Update the statistics from the device registers. */ lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6); lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6); - sti(); + spin_unlock_irqrestore(&lp->lock, flags); return &lp->stats; } @@ -916,7 +1404,9 @@ net_get_stats(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; + unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); if(dev->flags&IFF_PROMISC) { lp->rx_mode = RX_ALL_ACCEPT; @@ -935,18 +1425,23 @@ static void set_multicast_list(struct net_device *dev) /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */ writereg(dev, PP_RxCFG, lp->curr_rx_cfg | (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0)); + spin_unlock_irqrestore(&lp->lock, flags); } static int set_mac_address(struct net_device *dev, void *addr) { int i; + if (netif_running(dev)) return -EBUSY; - printk("%s: Setting MAC address to ", dev->name); - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); - printk(".\n"); + if (net_debug) + { + printk("%s: Setting MAC address to ", dev->name); + for (i = 0; i < 6; i++) + printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); + printk(".\n"); + } /* set the Ethernet address */ for (i=0; i < ETH_ALEN/2; i++) writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8)); @@ -963,17 +1458,31 @@ static struct net_device dev_cs89x0 = { 0, 0, 0, 0, 0, NULL, NULL }; +/* + * Support the 'debug' module parm even if we're compiled for non-debug to + * avoid breaking someone's startup scripts + */ + static int io=0; static int irq=0; static int debug=0; static char media[8]; static int duplex=-1; +static int use_dma = 0; /* These generate unused var warnings if ALLOW_DMA = 0 */ +static int dma=0; +static int dmasize=16; /* or 64 */ + MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(media, "s"); MODULE_PARM(duplex, "i"); +MODULE_PARM(dma , "i"); +MODULE_PARM(dmasize , "i"); +MODULE_PARM(use_dma , "i"); + +MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>"); EXPORT_NO_SYMBOLS; @@ -1008,15 +1517,34 @@ init_module(void) { struct net_local *lp; +#if DEBUGGING net_debug = debug; +#endif dev_cs89x0.name = namespace; dev_cs89x0.irq = irq; dev_cs89x0.base_addr = io; + dev_cs89x0.init = cs89x0_probe; dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); + if (dev_cs89x0.priv == 0) + { + printk(KERN_ERR "cs89x0.c: Out of memory.\n"); + return -ENOMEM; + } memset(dev_cs89x0.priv, 0, sizeof(struct net_local)); lp = (struct net_local *)dev_cs89x0.priv; +#if ALLOW_DMA + if (use_dma) + { + lp->use_dma = use_dma; + lp->dma = dma; + lp->dmasize = dmasize; + } +#endif + + spin_lock_init(&lp->lock); + /* boy, they'd better get these right */ if (!strcmp(media, "rj45")) lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T; @@ -1031,12 +1559,20 @@ init_module(void) lp->auto_neg_cnf = AUTO_NEG_ENABLE; if (io == 0) { - printk(KERN_NOTICE "cs89x0.c: Module autoprobing not allowed.\n"); - printk(KERN_NOTICE "cs89x0.c: Append io=0xNNN\n"); + printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n"); + printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n"); return -EPERM; } + +#if ALLOW_DMA + if (use_dma && dmasize != 16 && dmasize != 64) { + printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize); + return -EPERM; + } +#endif + if (register_netdev(&dev_cs89x0) != 0) { - printk(KERN_WARNING "cs89x0.c: No card found at 0x%x\n", io); + printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io); return -ENXIO; } return 0; @@ -1045,13 +1581,7 @@ init_module(void) void cleanup_module(void) { - -#endif -#ifdef MODULE - outw(0, dev_cs89x0.base_addr + ADD_PORT); -#endif -#ifdef MODULE - + outw(PP_ChipID, dev_cs89x0.base_addr + ADD_PORT); if (dev_cs89x0.priv != NULL) { /* Free up the private structure, or leak memory :-) */ unregister_netdev(&dev_cs89x0); diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index 7e78805af..d05ca7a42 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h @@ -217,6 +217,7 @@ #define ENDEC_LOOPBACK 0x0200 #define AUI_LOOPBACK 0x0400 #define BACKOFF_OFF 0x0800 +#define FDX_8900 0x4000 #define FAST_TEST 0x8000 /* PP_RxEvent - Receive Event Bit definition - Read-only */ diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c index 6a8c8b412..f91796d31 100644 --- a/drivers/net/ncr885e.c +++ b/drivers/net/ncr885e.c @@ -1210,9 +1210,6 @@ static int __init ncr885e_probe(void) unsigned short cmd; unsigned char irq, latency; - if ( debug >= 0) - ncr885e_debug = debug; - while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885_ETHERNET, pdev )) != NULL ) { @@ -1399,9 +1396,6 @@ write_mii( unsigned long ioaddr, int reg, int data ) int init_module(void) { - if ( debug >= 0) - ncr885e_debug = debug; - return ncr885e_probe(); } diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c index b4fc3e0a8..96959300f 100644 --- a/drivers/net/net_init.c +++ b/drivers/net/net_init.c @@ -69,18 +69,24 @@ static struct net_device *init_alloc_dev(int sizeof_priv) { struct net_device *dev; - int alloc_size = sizeof(struct net_device) + IFNAMSIZ - + sizeof_priv + 3; - alloc_size &= ~3; /* Round to dword boundary. */ - dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL); - if(dev==NULL) + int alloc_size; + + /* 32-byte alignment */ + alloc_size = sizeof (*dev) + IFNAMSIZ + sizeof_priv + 31; + alloc_size &= ~31; + + dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); + if (dev == NULL) { printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n"); return NULL; } + memset(dev, 0, alloc_size); + if (sizeof_priv) dev->priv = (void *) (dev + 1); + dev->name = sizeof_priv + (char *)(dev + 1); return dev; } diff --git a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c index 5d72f7778..3ef45a297 100644 --- a/drivers/net/pcmcia/aironet4500_cs.c +++ b/drivers/net/pcmcia/aironet4500_cs.c @@ -15,8 +15,7 @@ static const char *awc_version = #include <linux/module.h> -//#include <pcmcia/config.h> - +#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/ptrace.h> @@ -604,7 +603,7 @@ static int awc_event(event_t event, int priority, -int init_module(void) +static int aironet_cs_init(void) { servinfo_t serv; @@ -621,7 +620,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void aironet_cs_exit(void) { DEBUG(0, "awc_cs: unloading %c ",'\n'); unregister_pcmcia_driver(&dev_info); @@ -636,4 +635,6 @@ void cleanup_module(void) // awc_detach(dev_list); } - +module_init(aironet_cs_init); +module_exit(aironet_cs_init); + diff --git a/drivers/net/tokenring/Config.in b/drivers/net/tokenring/Config.in index b7e67fbad..31688f34d 100644 --- a/drivers/net/tokenring/Config.in +++ b/drivers/net/tokenring/Config.in @@ -3,7 +3,7 @@ # mainmenu_option next_comment -comment 'Token Ring driver support' +comment 'Token Ring devices' bool 'Token Ring driver support' CONFIG_TR if [ "$CONFIG_TR" != "n" ]; then diff --git a/drivers/net/tokenring/Makefile b/drivers/net/tokenring/Makefile index 65dfefc70..bf48c15e4 100644 --- a/drivers/net/tokenring/Makefile +++ b/drivers/net/tokenring/Makefile @@ -5,73 +5,29 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -# Note 2! The CFLAGS definition is now inherited from the -# parent makefile. -# -# -# Note : at this point, these files are compiled on all systems. -# In the future, some of these should be built conditionally. -# - -SUB_DIRS := +SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) +obj-y := +obj-n := +obj-m := +obj- := +export-objs := -L_TARGET := tr.a -L_OBJS := -M_OBJS := - -ifeq ($(CONFIG_IBMTR),y) - L_OBJS += ibmtr.o -else - ifeq ($(CONFIG_IBMTR),m) - M_OBJS += ibmtr.o - endif -endif - -ifeq ($(CONFIG_IBMOL),y) - L_OBJS += olympic.o -else - ifeq ($(CONFIG_IBMOL),m) - M_OBJS += olympic.o - endif -endif - -ifeq ($(CONFIG_TMS380TR),y) - L_OBJS += tms380tr.o - ifeq ($(CONFIG_ABYSS),y) - L_OBJS += abyss.o - endif - ifeq ($(CONFIG_MADGEMC),y) - L_OBJS += madgemc.o - endif - ifeq ($(CONFIG_TMSPCI),y) - L_OBJS += tmspci.o - endif -else - ifeq ($(CONFIG_TMS380TR),m) - M_OBJS += tms380tr.o - ifeq ($(CONFIG_ABYSS),m) - M_OBJS += abyss.o - endif - ifeq ($(CONFIG_MADGEMC),m) - M_OBJS += madgemc.o - endif - ifeq ($(CONFIG_TMSPCI),m) - M_OBJS += tmspci.o - endif - endif -endif +obj-$(CONFIG_IBMTR) += ibmtr.o +obj-$(CONFIG_IBMOL) += olympic.o +obj-$(CONFIG_TMS380TR) += tms380tr.o +obj-$(CONFIG_ABYSS) += abyss.o +obj-$(CONFIG_MADGEMC) += madgemc.o +obj-$(CONFIG_TMSPCI) += tmspci.o +obj-$(CONFIG_SMCTR) += smctr.o -ifeq ($(CONFIG_SMCTR),y) - L_OBJS += smctr.o -else - ifeq ($(CONFIG_SMCTR),m) - M_OBJS += smctr.o - endif -endif +L_TARGET := tr.a +L_OBJS := $(filter-out $(export-objs), $(obj-y)) +LX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) include $(TOPDIR)/Rules.make - diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index abfde3e8a..bbca052e7 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -17,10 +17,21 @@ Support and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html + + + Linux kernel version history: + + LK1.1.0: + - Jeff Garzik: softnet 'n stuff + + LK1.1.1: + - Justin Guyett: softnet and locking fixes + - Jeff Garzik: use PCI interface + */ static const char *versionA = -"via-rhine.c:v1.01 2/27/99 Written by Donald Becker\n"; +"via-rhine.c:v1.01-LK1.1.1 3/2/2000 Written by Donald Becker\n"; static const char *versionB = " http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n"; @@ -29,7 +40,6 @@ static const char *versionB = static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; -static int min_pci_latency = 64; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ @@ -112,7 +122,6 @@ static const int multicast_filter_limit = 32; MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>"); MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(min_pci_latency, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); @@ -157,7 +166,7 @@ buffers. When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is copied to the new skbuff. When the incoming frame is larger, the skbuff is passed directly up the protocol stack. Buffers consumed this way are replaced by newly allocated -skbuffs in the last phase of netdev_rx(). +skbuffs in the last phase of via_rhine_rx(). The RX_COPYBREAK value is chosen to trade-off the memory wasted by using a full-sized skbuff for small frames vs. the copying costs of larger @@ -208,34 +217,50 @@ The chip does not pad to minimum transmit length. */ - + /* This table drives the PCI probe routines. It's mostly boilerplate in all of the drivers, and will likely be provided by some future kernel. Note the matching code -- the first table entry matchs all 56** cards but second only the 1234 card. */ + enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; -struct pci_id_info { + +enum via_rhine_chips { + vt86c100a = 0, + vt3043, +}; + +struct via_rhine_chip_info { const char *name; - u16 vendor_id, device_id, device_id_mask, flags; + u16 flags; int io_size; - struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt); }; -static struct net_device *via_probe1(struct pci_dev *pdev, long ioaddr, int irq, - int chp_idx, int fnd_cnt); -static struct pci_id_info pci_tbl[] = { - { "VIA VT86C100A Rhine-II", 0x1106, 0x6100, 0xffff, - PCI_USES_MEM|PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1}, - { "VIA VT3043 Rhine", 0x1106, 0x3043, 0xffff, - PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1}, - {0,}, /* 0 terminated list. */ +/* directly indexed by enum via_rhine_chips, above */ +static struct via_rhine_chip_info via_rhine_chip_info[] __devinitdata = +{ + {"VIA VT86C100A Rhine-II", + PCI_USES_MEM | PCI_USES_IO | PCI_USES_MEM | PCI_USES_MASTER, + 128,}, + {"VIA VT3043 Rhine", + PCI_USES_IO | PCI_USES_MEM | PCI_USES_MASTER, + 128,}, +}; + +static struct pci_device_id via_rhine_pci_tbl[] __devinitdata = +{ + {0x1106, 0x6100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt86c100a}, + {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt3043}, + {0,}, /* terminate list */ }; +MODULE_DEVICE_TABLE(pci, via_rhine_pci_tbl); + /* A chip capabilities table, matching the entries in pci_tbl[] above. */ @@ -315,16 +340,14 @@ struct netdev_private { struct sk_buff* tx_skbuff[TX_RING_SIZE]; unsigned char *tx_buf[TX_RING_SIZE]; /* Tx bounce buffers */ unsigned char *tx_bufs; /* Tx bounce buffer region. */ - struct net_device *next_module; /* Link for devices of this type. */ struct net_device_stats stats; struct timer_list timer; /* Media monitoring timer. */ spinlock_t lock; /* Frequently used values: keep some adjacent for cache effect. */ int chip_id; - long in_interrupt; /* Word-long for SMP locks. */ struct rx_desc *rx_head_desc; - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ - unsigned int cur_tx, dirty_tx; + unsigned short int cur_rx, dirty_rx; /* Producer/consumer ring indices */ + unsigned short int cur_tx, dirty_tx; unsigned int rx_buf_sz; /* Based on MTU+slack. */ u16 chip_cmd; /* Current setting for ChipCmd */ unsigned int tx_full:1; /* The Tx queue is full. */ @@ -342,136 +365,94 @@ struct netdev_private { static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); -static int netdev_open(struct net_device *dev); -static void check_duplex(struct net_device *dev); -static void netdev_timer(unsigned long data); -static void tx_timeout(struct net_device *dev); -static void init_ring(struct net_device *dev); -static int start_tx(struct sk_buff *skb, struct net_device *dev); -static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs); -static int netdev_rx(struct net_device *dev); -static void netdev_error(struct net_device *dev, int intr_status); -static void set_rx_mode(struct net_device *dev); -static struct net_device_stats *get_stats(struct net_device *dev); +static int via_rhine_open(struct net_device *dev); +static void via_rhine_check_duplex(struct net_device *dev); +static void via_rhine_timer(unsigned long data); +static void via_rhine_tx_timeout(struct net_device *dev); +static void via_rhine_init_ring(struct net_device *dev); +static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev); +static void via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static void via_rhine_tx(struct net_device *dev); +static void via_rhine_rx(struct net_device *dev); +static void via_rhine_error(struct net_device *dev, int intr_status); +static void via_rhine_set_rx_mode(struct net_device *dev); +static struct net_device_stats *via_rhine_get_stats(struct net_device *dev); static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int netdev_close(struct net_device *dev); - - +static int via_rhine_close(struct net_device *dev); -/* A list of our installed devices, for removing the driver module. */ -static struct net_device *root_net_dev = NULL; -/* Ideally we would detect all network cards in slot order. That would - be best done a central PCI probe dispatch, which wouldn't work - well when dynamically adding drivers. So instead we detect just the - cards we know about in slot order. */ - -static int pci_etherdev_probe(struct pci_id_info pci_tbl[]) +static int __devinit via_rhine_init_one (struct pci_dev *pdev, + const struct pci_device_id *ent) { - int cards_found = 0; - int pci_index = 0; - unsigned char pci_bus, pci_device_fn; struct net_device *dev; + struct netdev_private *np; + int i, option; + int chip_id = (int) ent->driver_data; + int irq = pdev->irq; + static int card_idx = -1; + static int did_version = 0; + long ioaddr; + int io_size; + + /* print version once and once only */ + if (! did_version++) { + printk (KERN_INFO "%s", versionA); + printk (KERN_INFO "%s", versionB); + } + + card_idx++; + option = card_idx < MAX_UNITS ? options[card_idx] : 0; + io_size = via_rhine_chip_info[chip_id].io_size; - for (;pci_index < 0xff; pci_index++) { - u16 vendor, device, pci_command, new_command; - int chip_idx, irq; - long pciaddr; - long ioaddr; - struct pci_dev *pdev; - - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - - pdev = pci_find_slot (pci_bus, pci_device_fn); - if (!pdev) continue; - vendor = pdev->vendor; - device = pdev->device; - - for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) - if (vendor == pci_tbl[chip_idx].vendor_id - && (device & pci_tbl[chip_idx].device_id_mask) == - pci_tbl[chip_idx].device_id) - break; - if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ - continue; #ifdef VIA_USE_IO - pciaddr = pdev->resource[0].start; + ioaddr = pci_resource_start (pdev, 0); #else - pciaddr = pdev->resource[1].start; + ioaddr = pci_resource_start (pdev, 1); #endif - irq = pdev->irq; - - if (debug > 2) - printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n", - pci_tbl[chip_idx].name, pciaddr, irq); - - if (pci_tbl[chip_idx].flags & PCI_USES_IO) { - ioaddr = pciaddr & ~3; - if (check_region(ioaddr, pci_tbl[chip_idx].io_size)) - continue; - } else if ((ioaddr = (long)ioremap(pciaddr & ~0xf, - pci_tbl[chip_idx].io_size)) == 0) { - printk(KERN_INFO "Failed to map PCI address %#lx.\n", - pciaddr); - continue; - } - - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - new_command = pci_command | (pci_tbl[chip_idx].flags & 7); - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled the" - " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", - pdev->bus->number, pdev->devfn, pci_command, new_command); - pci_write_config_word(pdev, PCI_COMMAND, new_command); - } - - dev = pci_tbl[chip_idx].probe1(pdev, ioaddr, irq, chip_idx, cards_found); - if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { - u8 pci_latency; - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < min_pci_latency) { - printk(KERN_INFO " PCI latency timer (CFLT) is " - "unreasonably low at %d. Setting to %d clocks.\n", - pci_latency, min_pci_latency); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency); - } - } - dev = 0; - cards_found++; + if (pci_enable_device (pdev)) { + printk (KERN_ERR "unable to init PCI device (card #%d)\n", + card_idx); + goto err_out; + } + + if (via_rhine_chip_info[chip_id].flags & PCI_USES_MASTER) + pci_set_master (pdev); + + dev = init_etherdev(NULL, sizeof (*np)); + if (dev == NULL) { + printk (KERN_ERR "init_ethernet failed for card #%d\n", + card_idx); + goto err_out; + } + + if (!request_region(pci_resource_start (pdev, 0), io_size, dev->name)) { + printk (KERN_ERR "request_region failed for device %s, region 0x%X @ 0x%lX\n", + dev->name, io_size, + pci_resource_start (pdev, 0)); + goto err_out_free_netdev; + } + if (!request_mem_region(pci_resource_start (pdev, 1), io_size, dev->name)) { + printk (KERN_ERR "request_mem_region failed for device %s, region 0x%X @ 0x%lX\n", + dev->name, io_size, + pci_resource_start (pdev, 1)); + goto err_out_free_pio; } - return cards_found ? 0 : -ENODEV; -} - - -static struct net_device *via_probe1(struct pci_dev *pdev, - long ioaddr, int irq, - int chip_id, int card_idx) -{ - struct net_device *dev; - struct netdev_private *np; - int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0; - - dev = init_etherdev(NULL, 0); - if(dev==NULL) - return NULL; - - printk(KERN_INFO "%s: %s at 0x%lx, ", - dev->name, pci_tbl[chip_id].name, ioaddr); - -#ifdef VIA_USE_IO - if (!request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name)) { - unregister_netdev (dev); - kfree (dev); - return NULL; +#ifndef VIA_USE_IO + ioaddr = (long) ioremap (ioaddr, io_size); + if (!ioaddr) { + printk (KERN_ERR "ioremap failed for device %s, region 0x%X @ 0x%X\n", + dev->name, io_size, + pci_resource_start (pdev, 1)); + goto err_out_free_mmio; } #endif + printk(KERN_INFO "%s: %s at 0x%lx, ", + dev->name, via_rhine_chip_info[chip_id].name, ioaddr); + /* Ideally we would be read the EEPROM but access may be locked. */ for (i = 0; i <6; i++) dev->dev_addr[i] = readb(ioaddr + StationAddr + i); @@ -485,16 +466,8 @@ static struct net_device *via_probe1(struct pci_dev *pdev, dev->base_addr = ioaddr; dev->irq = irq; - /* Make certain the descriptor lists are cache-aligned. */ - np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 31) & ~31); - /* FIXME! check return !!! */ - memset(np, 0, sizeof(*np)); - dev->priv = np; - - np->next_module = root_net_dev; - root_net_dev = dev; - - np->lock = SPIN_LOCK_UNLOCKED; + np = dev->priv; + spin_lock_init (&np->lock); np->chip_id = chip_id; if (dev->mem_start) @@ -515,14 +488,16 @@ static struct net_device *via_probe1(struct pci_dev *pdev, np->duplex_lock = 1; /* The chip-specific entries in the device structure. */ - dev->open = &netdev_open; - dev->hard_start_xmit = &start_tx; - dev->stop = &netdev_close; - dev->get_stats = &get_stats; - dev->set_multicast_list = &set_rx_mode; - dev->do_ioctl = &mii_ioctl; - dev->tx_timeout = tx_timeout; + dev->open = via_rhine_open; + dev->hard_start_xmit = via_rhine_start_tx; + dev->stop = via_rhine_close; + dev->get_stats = via_rhine_get_stats; + dev->set_multicast_list = via_rhine_set_rx_mode; + dev->do_ioctl = mii_ioctl; + dev->tx_timeout = via_rhine_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + + pdev->driver_data = dev; if (cap_tbl[np->chip_id].flags & CanHaveMII) { int phy, phy_idx = 0; @@ -541,10 +516,25 @@ static struct net_device *via_probe1(struct pci_dev *pdev, np->mii_cnt = phy_idx; } - return dev; + return 0; + +#ifndef VIA_USE_IO +/* note this is ifdef'd because the ioremap is ifdef'd... + * so additional exit conditions above this must move + * release_mem_region outside of the ifdef */ +err_out_free_mmio: + release_mem_region(pci_resource_start (pdev, 1), io_size, dev->name)); +#endif +err_out_free_pio: + release_region(pci_resource_start (pdev, 0), io_size); +err_out_free_netdev: + unregister_netdev (dev); + kfree (dev); +err_out: + return -ENODEV; } - + /* Read and write over the MII Management Data I/O (MDIO) interface. */ static int mdio_read(struct net_device *dev, int phy_id, int regnum) @@ -581,8 +571,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value return; } - -static int netdev_open(struct net_device *dev) + +static int via_rhine_open(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; @@ -591,16 +581,16 @@ static int netdev_open(struct net_device *dev) /* Reset the chip. */ writew(CmdReset, ioaddr + ChipCmd); - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) + if (request_irq(dev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; if (debug > 1) - printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", + printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n", dev->name, dev->irq); MOD_INC_USE_COUNT; - init_ring(dev); + via_rhine_init_ring(dev); writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr); writel(virt_to_bus(np->tx_ring), ioaddr + TxRingPtr); @@ -613,15 +603,14 @@ static int netdev_open(struct net_device *dev) /* Configure the FIFO thresholds. */ writeb(0x20, ioaddr + TxConfig); /* Initial threshold 32 bytes */ np->tx_thresh = 0x20; - np->rx_thresh = 0x60; /* Written in set_rx_mode(). */ + np->rx_thresh = 0x60; /* Written in via_rhine_set_rx_mode(). */ if (dev->if_port == 0) dev->if_port = np->default_port; netif_start_queue(dev); - np->in_interrupt = 0; - set_rx_mode(dev); + via_rhine_set_rx_mode(dev); /* Enable interrupts by setting the interrupt mask. */ writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped| @@ -634,10 +623,10 @@ static int netdev_open(struct net_device *dev) np->chip_cmd |= CmdFDuplex; writew(np->chip_cmd, ioaddr + ChipCmd); - check_duplex(dev); + via_rhine_check_duplex(dev); if (debug > 2) - printk(KERN_DEBUG "%s: Done netdev_open(), status %4.4x " + printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x " "MII status: %4.4x.\n", dev->name, readw(ioaddr + ChipCmd), mdio_read(dev, np->phys[0], 1)); @@ -646,22 +635,23 @@ static int netdev_open(struct net_device *dev) init_timer(&np->timer); np->timer.expires = RUN_AT(1); np->timer.data = (unsigned long)dev; - np->timer.function = &netdev_timer; /* timer handler */ + np->timer.function = &via_rhine_timer; /* timer handler */ add_timer(&np->timer); return 0; } -static void check_duplex(struct net_device *dev) +static void via_rhine_check_duplex(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; int mii_reg5 = mdio_read(dev, np->phys[0], 5); + int negotiated = mii_reg5 & np->advertising; int duplex; if (np->duplex_lock || mii_reg5 == 0xffff) return; - duplex = (mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040; + duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; if (np->full_duplex != duplex) { np->full_duplex = duplex; if (debug) @@ -676,7 +666,7 @@ static void check_duplex(struct net_device *dev) } } -static void netdev_timer(unsigned long data) +static void via_rhine_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct netdev_private *np = (struct netdev_private *)dev->priv; @@ -687,41 +677,41 @@ static void netdev_timer(unsigned long data) printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); } - check_duplex(dev); + via_rhine_check_duplex(dev); np->timer.expires = RUN_AT(next_tick); add_timer(&np->timer); } -static void tx_timeout(struct net_device *dev) +static void via_rhine_tx_timeout (struct net_device *dev) { - struct netdev_private *np = (struct netdev_private *)dev->priv; + struct netdev_private *np = (struct netdev_private *) dev->priv; long ioaddr = dev->base_addr; - printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " - "%4.4x, resetting...\n", - dev->name, readw(ioaddr + IntrStatus), - mdio_read(dev, np->phys[0], 1)); + printk (KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " + "%4.4x, resetting...\n", + dev->name, readw (ioaddr + IntrStatus), + mdio_read (dev, np->phys[0], 1)); - /* Perhaps we should reinitialize the hardware here. */ - dev->if_port = 0; - /* Stop and restart the chip's Tx processes . */ + /* Perhaps we should reinitialize the hardware here. */ + dev->if_port = 0; + /* Stop and restart the chip's Tx processes . */ - /* Trigger an immediate transmit demand. */ + /* Trigger an immediate transmit demand. */ - dev->trans_start = jiffies; - np->stats.tx_errors++; - return; + dev->trans_start = jiffies; + np->stats.tx_errors++; + + netif_start_queue (dev); } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void init_ring(struct net_device *dev) +static void via_rhine_init_ring(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; int i; - np->tx_full = 0; np->cur_rx = np->cur_tx = 0; np->dirty_rx = np->dirty_tx = 0; @@ -749,7 +739,6 @@ static void init_ring(struct net_device *dev) np->rx_ring[i].rx_status = 0; np->rx_ring[i].rx_length = DescOwn; } - np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); for (i = 0; i < TX_RING_SIZE; i++) { np->tx_skbuff[i] = 0; @@ -763,14 +752,18 @@ static void init_ring(struct net_device *dev) return; } -static int start_tx(struct sk_buff *skb, struct net_device *dev) +static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; unsigned entry; + unsigned long flags; /* Caution: the write order is important here, set the field with the "ownership" bits last. */ + /* lock eth irq */ + spin_lock_irqsave (&np->lock, flags); + /* Calculate the next Tx descriptor entry. */ entry = np->cur_tx % TX_RING_SIZE; @@ -796,12 +789,13 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) /* Wake the potentially-idle transmit channel. */ writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); - if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1) - netif_start_queue(dev); /* Typical path */ - else - np->tx_full = 1; + if (np->cur_tx == np->dirty_tx + TX_RING_SIZE) + netif_stop_queue(dev); + dev->trans_start = jiffies; + spin_unlock_irqrestore (&np->lock, flags); + if (debug > 4) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", dev->name, np->cur_tx, entry); @@ -811,20 +805,15 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) +static void via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = (struct net_device *)dev_instance; - struct netdev_private *np; long ioaddr, boguscnt = max_interrupt_work; + u32 intr_status; ioaddr = dev->base_addr; - np = (struct netdev_private *)dev->priv; - spin_lock (&np->lock); - - do { - u32 intr_status = readw(ioaddr + IntrStatus); - + while ((intr_status = readw(ioaddr + IntrStatus))) { /* Acknowledge all of the current interrupt sources ASAP. */ writew(intr_status & 0xffff, ioaddr + IntrStatus); @@ -832,54 +821,18 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name, intr_status); - if (intr_status == 0) - break; - if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) - netdev_rx(dev); - - for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { - int entry = np->dirty_tx % TX_RING_SIZE; - int txstatus; - if (np->tx_ring[entry].tx_own) - break; - txstatus = np->tx_ring[entry].tx_status; - if (debug > 6) - printk(KERN_DEBUG " Tx scavenge %d status %4.4x.\n", - entry, txstatus); - if (txstatus & 0x8000) { - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %4.4x.\n", - dev->name, txstatus); - np->stats.tx_errors++; - if (txstatus & 0x0400) np->stats.tx_carrier_errors++; - if (txstatus & 0x0200) np->stats.tx_window_errors++; - if (txstatus & 0x0100) np->stats.tx_aborted_errors++; - if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++; - if (txstatus & 0x0002) np->stats.tx_fifo_errors++; - /* Transmitter restarted in 'abnormal' handler. */ - } else { - np->stats.collisions += (txstatus >> 3) & 15; - np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff; - np->stats.tx_packets++; - } - /* Free the original skb. */ - dev_kfree_skb_irq(np->tx_skbuff[entry]); - np->tx_skbuff[entry] = 0; - } - if (np->tx_full && - netif_queue_stopped(dev) && - np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { - /* The ring is no longer full, clear tbusy. */ - np->tx_full = 0; - netif_wake_queue (dev); - } + via_rhine_rx(dev); + + if (intr_status & (IntrTxDone | IntrTxAbort | IntrTxUnderrun | + IntrTxAborted)) + via_rhine_tx(dev); /* Abnormal error summary/uncommon events handlers. */ if (intr_status & (IntrPCIErr | IntrLinkChange | IntrMIIChange | IntrStatsMax | IntrTxAbort | IntrTxUnderrun)) - netdev_error(dev, intr_status); + via_rhine_error(dev, intr_status); if (--boguscnt < 0) { printk(KERN_WARNING "%s: Too much work at interrupt, " @@ -887,25 +840,67 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) dev->name, intr_status); break; } - } while (1); + } if (debug > 3) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); +} + +/* This routine is logically part of the interrupt handler, but isolated + for clarity and better register allocation. */ +static void via_rhine_tx(struct net_device *dev) +{ + struct netdev_private *np = (struct netdev_private *)dev->priv; + int txstatus = 0, entry = np->dirty_tx % TX_RING_SIZE; + + spin_lock (&np->lock); + + /* if tx_full is set, they're all dirty, not clean */ + while (np->dirty_tx != np->cur_tx) { + if (np->tx_ring[entry].tx_own) /* transmit request pending */ + break; + txstatus = np->tx_ring[entry].tx_status; + if (debug > 6) + printk(KERN_DEBUG " Tx scavenge %d status %4.4x.\n", + entry, txstatus); + if (txstatus & 0x8000) { + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %4.4x.\n", + dev->name, txstatus); + np->stats.tx_errors++; + if (txstatus & 0x0400) np->stats.tx_carrier_errors++; + if (txstatus & 0x0200) np->stats.tx_window_errors++; + if (txstatus & 0x0100) np->stats.tx_aborted_errors++; + if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++; + if (txstatus & 0x0002) np->stats.tx_fifo_errors++; + /* Transmitter restarted in 'abnormal' handler. */ + } else { + np->stats.collisions += (txstatus >> 3) & 15; + np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff; + np->stats.tx_packets++; + } + /* Free the original skb. */ + dev_kfree_skb_irq(np->tx_skbuff[entry]); + np->tx_skbuff[entry] = NULL; + entry = (++np->dirty_tx) % TX_RING_SIZE; + } + if ((np->cur_tx - np->dirty_tx) <= TX_RING_SIZE/2) + netif_wake_queue (dev); spin_unlock (&np->lock); } /* This routine is logically part of the interrupt handler, but isolated for clarity and better register allocation. */ -static int netdev_rx(struct net_device *dev) +static void via_rhine_rx(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; - int entry = np->cur_rx % RX_RING_SIZE; - int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; + int entry = (np->dirty_rx = np->cur_rx) % RX_RING_SIZE; + int boguscnt = RX_RING_SIZE; if (debug > 4) { - printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n", + printk(KERN_DEBUG " In via_rhine_rx(), entry %d status %4.4x.\n", entry, np->rx_head_desc->rx_length); } @@ -916,7 +911,7 @@ static int netdev_rx(struct net_device *dev) u16 desc_status = desc->rx_status; if (debug > 4) - printk(KERN_DEBUG " netdev_rx() status is %4.4x.\n", + printk(KERN_DEBUG " via_rhine_rx() status is %4.4x.\n", desc_status); if (--boguscnt < 0) break; @@ -924,15 +919,15 @@ static int netdev_rx(struct net_device *dev) if ((desc_status & RxWholePkt) != RxWholePkt) { printk(KERN_WARNING "%s: Oversized Ethernet frame spanned " "multiple buffers, entry %#x length %d status %4.4x!\n", - dev->name, np->cur_rx, data_size, desc_status); + dev->name, entry, data_size, desc_status); printk(KERN_WARNING "%s: Oversized Ethernet frame %p vs %p.\n", dev->name, np->rx_head_desc, - &np->rx_ring[np->cur_rx % RX_RING_SIZE]); + &np->rx_ring[entry]); np->stats.rx_length_errors++; } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", + printk(KERN_DEBUG " via_rhine_rx() Rx error was %8.8x.\n", desc_status); np->stats.rx_errors++; if (desc_status & 0x0030) np->stats.rx_length_errors++; @@ -973,9 +968,9 @@ static int netdev_rx(struct net_device *dev) } /* Refill the Rx ring buffers. */ - for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) { + while (np->dirty_rx != np->cur_rx) { struct sk_buff *skb; - entry = np->dirty_rx % RX_RING_SIZE; + entry = np->dirty_rx++ % RX_RING_SIZE; if (np->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(np->rx_buf_sz); np->rx_skbuff[entry] = skb; @@ -990,10 +985,9 @@ static int netdev_rx(struct net_device *dev) /* Pre-emptively restart Rx engine. */ writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd); - return 0; } -static void netdev_error(struct net_device *dev, int intr_status) +static void via_rhine_error(struct net_device *dev, int intr_status) { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; @@ -1003,7 +997,7 @@ static void netdev_error(struct net_device *dev, int intr_status) /* Link failed, restart autonegotiation. */ mdio_write(dev, np->phys[0], 0, 0x3300); else - check_duplex(dev); + via_rhine_check_duplex(dev); if (debug) printk(KERN_ERR "%s: MII status changed: Autonegotiation " "advertising %4.4x partner %4.4x.\n", dev->name, @@ -1026,7 +1020,7 @@ static void netdev_error(struct net_device *dev, int intr_status) printk(KERN_INFO "%s: Transmitter underrun, increasing Tx " "threshold setting to %2.2x.\n", dev->name, np->tx_thresh); } - if ((intr_status & ~(IntrLinkChange|IntrStatsMax|IntrTxAbort)) && debug) { + if ((intr_status & ~(IntrLinkChange|IntrStatsMax|IntrTxAbort)) && debug > 1) { printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); /* Recovery for other fault sources not known. */ @@ -1034,7 +1028,7 @@ static void netdev_error(struct net_device *dev, int intr_status) } } -static struct enet_statistics *get_stats(struct net_device *dev) +static struct net_device_stats *via_rhine_get_stats(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; @@ -1068,7 +1062,7 @@ static inline u32 ether_crc(int length, unsigned char *data) return crc; } -static void set_rx_mode(struct net_device *dev) +static void via_rhine_set_rx_mode(struct net_device *dev) { struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; @@ -1120,7 +1114,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } -static int netdev_close(struct net_device *dev) +static int via_rhine_close(struct net_device *dev) { long ioaddr = dev->base_addr; struct netdev_private *np = (struct netdev_private *)dev->priv; @@ -1162,45 +1156,49 @@ static int netdev_close(struct net_device *dev) return 0; } -static int __init via_rhine_init_module (void) + +static void __devexit via_rhine_remove_one (struct pci_dev *pdev) { - if (debug) /* Emit version even if no cards detected. */ - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); -#ifdef CARDBUS - register_driver(ðerdev_ops); - return 0; -#else - return pci_etherdev_probe(pci_tbl); + struct net_device *dev = pdev->driver_data; + struct netdev_private *np = (struct netdev_private *)(dev->priv); + + unregister_netdev(dev); + + release_region(pci_resource_start (pdev, 0), + via_rhine_chip_info[np->chip_id].io_size); + release_mem_region(pci_resource_start (pdev, 1), + via_rhine_chip_info[np->chip_id].io_size); + +#ifndef VIA_USE_IO + iounmap((char *)(dev->base_addr)); #endif + + kfree(dev); } -static void __exit via_rhine_cleanup_module (void) + +static struct pci_driver via_rhine_driver = { + name: "via-rhine", + id_table: via_rhine_pci_tbl, + probe: via_rhine_init_one, + remove: via_rhine_remove_one, +}; + + +static int __init via_rhine_init (void) { + return pci_module_init (&via_rhine_driver); +} -#ifdef CARDBUS - unregister_driver(ðerdev_ops); -#endif - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (root_net_dev) { - struct netdev_private *np = - (struct netdev_private *)(root_net_dev->priv); - unregister_netdev(root_net_dev); -#ifdef VIA_USE_IO - release_region(root_net_dev->base_addr, pci_tbl[np->chip_id].io_size); -#else - iounmap((char *)(root_net_dev->base_addr)); -#endif - kfree(root_net_dev); - root_net_dev = np->next_module; -#if 0 - kfree(np); /* Assumption: no struct realignment. */ -#endif - } +static void __exit via_rhine_cleanup (void) +{ + pci_unregister_driver (&via_rhine_driver); } -module_init(via_rhine_init_module); -module_exit(via_rhine_cleanup_module); + +module_init(via_rhine_init); +module_exit(via_rhine_cleanup); /* diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 7eb759b94..85febe47d 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1263,7 +1263,7 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, real_ioaddr = ioaddr = pci_resource_start (pdev, 0); #else real_ioaddr = ioaddr = pci_resource_start (pdev, 1); - ioaddr = ioremap(ioaddr, YELLOWFIN_SIZE); + ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE); #endif irq = pdev->irq; |