diff options
Diffstat (limited to 'linux/src/drivers/net/ne2k-pci.c')
-rw-r--r-- | linux/src/drivers/net/ne2k-pci.c | 534 |
1 files changed, 268 insertions, 266 deletions
diff --git a/linux/src/drivers/net/ne2k-pci.c b/linux/src/drivers/net/ne2k-pci.c index 280fb72..2b2b1f4 100644 --- a/linux/src/drivers/net/ne2k-pci.c +++ b/linux/src/drivers/net/ne2k-pci.c @@ -2,39 +2,81 @@ /* A Linux device driver for PCI NE2000 clones. - Authorship and other copyrights: - 1992-1998 by Donald Becker, NE2000 core and various modifications. + Authors and other copyright holders: + 1992-2002 by Donald Becker, NE2000 core and various modifications. 1995-1998 by Paul Gortmaker, core modifications and PCI support. - Copyright 1993 assigned to the United States Government as represented by the Director, National Security Agency. - 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 as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. - People are making PCI ne2000 clones! Oh the horror, the horror... + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 Issues remaining: - No full-duplex support. + People are making PCI ne2000 clones! Oh the horror, the horror... + Limited full-duplex support. */ -/* Our copyright info must remain in the binary. */ -static const char *version = -"ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n"; +/* These identify the driver base version and may not be removed. */ +static const char version1[] = +"ne2k-pci.c:v1.05 6/13/2002 D. Becker/P. Gortmaker\n"; +static const char version2[] = +" http://www.scyld.com/network/ne2k-pci.html\n"; -#ifdef MODVERSIONS -#include <linux/modversions.h> +/* The user-configurable values. + These may be modified when a driver module is loaded.*/ + +static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ + +#define MAX_UNITS 8 /* More are supported, limit only on options */ +/* Used to pass the full-duplex flag, etc. */ +static int full_duplex[MAX_UNITS] = {0, }; +static int options[MAX_UNITS] = {0, }; + +/* Force a non std. amount of memory. Units are 256 byte pages. */ +/* #define PACKETBUF_MEMSIZE 0x40 */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif +#if !defined(__OPTIMIZE__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + +#include <linux/config.h> +#if defined(CONFIG_SMP) && ! defined(__SMP__) +#define __SMP__ +#endif +#if defined(MODULE) && defined(CONFIG_MODVERSIONS) && ! defined(MODVERSIONS) +#define MODVERSIONS #endif + +#include <linux/version.h> #include <linux/module.h> +#if LINUX_VERSION_CODE < 0x20300 && defined(MODVERSIONS) +#include <linux/modversions.h> +#endif + #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/errno.h> #include <linux/pci.h> -#include <linux/bios32.h> +#if LINUX_VERSION_CODE < 0x20200 +#define lock_8390_module() +#define unlock_8390_module() +#else +#include <linux/init.h> +#endif + #include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> @@ -43,8 +85,18 @@ static const char *version = #include <linux/etherdevice.h> #include "8390.h" -/* Set statically or when loading the driver module. */ -static int debug = 1; +#ifdef INLINE_PCISCAN +#include "k_compat.h" +#else +#include "pci-scan.h" +#include "kern_compat.h" +#endif + +MODULE_AUTHOR("Donald Becker / Paul Gortmaker"); +MODULE_DESCRIPTION("PCI NE2000 clone driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); /* Some defines that people can play with if so inclined. */ @@ -52,27 +104,52 @@ static int debug = 1; #ifdef LOAD_8390_BY_KERNELD #include <linux/kerneld.h> #endif -/* Use 32 bit data-movement operations instead of 16 bit. */ -#define USE_LONGIO -/* Do we implement the read before write bugfix ? */ -/* #define NE_RW_BUGFIX */ +static void *ne2k_pci_probe1(struct pci_dev *pdev, void *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); +/* Flags. We rename an existing ei_status field to store flags! */ +/* Thus only the low 8 bits are usable for non-init-time flags. */ +#define ne2k_flags reg0 +enum { + ONLY_16BIT_IO=8, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + FORCE_FDX=0x20, /* User override. */ + REALTEK_FDX=0x40, HOLTEK_FDX=0x80, + STOP_PG_0x60=0x100, +}; +#define NE_IO_EXTENT 0x20 +#ifndef USE_MEMORY_OPS +#define PCI_IOTYPE (PCI_USES_IO | PCI_ADDR0) +#else +#warning When using PCI memory mode the 8390 core must be compiled for memory +#warning operations as well. +#warning Not all PCI NE2000 clones support memory mode access. +#define PCI_IOTYPE (PCI_USES_MEM | PCI_ADDR1) +#endif -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ +static struct pci_id_info pci_id_tbl[] = { + {"RealTek RTL-8029",{ 0x802910ec, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, + REALTEK_FDX }, + {"Winbond 89C940", { 0x09401050, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + {"Winbond w89c940", { 0x5a5a1050, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + {"KTI ET32P2", { 0x30008e2e, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + {"NetVin NV5000SC", { 0x50004a14, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + {"Via 86C926", { 0x09261106, 0xffffffff}, + PCI_IOTYPE, NE_IO_EXTENT, ONLY_16BIT_IO}, + {"SureCom NE34", { 0x0e3410bd, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + {"Holtek HT80232", { 0x005812c3, 0xffffffff}, + PCI_IOTYPE, NE_IO_EXTENT, ONLY_16BIT_IO | HOLTEK_FDX}, + {"Holtek HT80229", { 0x559812c3, 0xffffffff}, + PCI_IOTYPE, NE_IO_EXTENT, ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60}, + {"Compex RL2000", + { 0x140111f6, 0xffffffff}, PCI_IOTYPE, NE_IO_EXTENT, 0}, + /* A mutant board: Winbond chip with a RTL format EEPROM. */ + {"Winbond w89c940 (misprogrammed type 0x1980)", { 0x19808c4a, 0xffffffff}, + PCI_IOTYPE, NE_IO_EXTENT, 0}, + {0,}, /* 0 terminated list. */ +}; -static struct { - unsigned short vendor, dev_id; - char *name; -} -pci_clone_list[] = { - {0x10ec, 0x8029, "RealTek RTL-8029"}, - {0x1050, 0x0940, "Winbond 89C940"}, - {0x11f6, 0x1401, "Compex RL2000"}, - {0x8e2e, 0x3000, "KTI ET32P2"}, - {0x4a14, 0x5000, "NetVin NV5000SC"}, - {0x1106, 0x0926, "Via 82C926"}, - {0,} +struct drv_id_info ne2k_pci_drv_id = { + "ne2k-pci", 0, PCI_CLASS_NETWORK_ETHERNET<<8, pci_id_tbl, ne2k_pci_probe1, }; /* ---- No user-serviceable parts below ---- */ @@ -81,41 +158,40 @@ pci_clone_list[] = { #define NE_CMD 0x00 #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ #define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ -#define NE_IO_EXTENT 0x20 #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -int ne2k_pci_probe(struct device *dev); -static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq); +int ne2k_pci_probe(struct net_device *dev); -static int ne_open(struct device *dev); -static int ne_close(struct device *dev); +static int ne2k_pci_open(struct net_device *dev); +static int ne2k_pci_close(struct net_device *dev); -static void ne_reset_8390(struct device *dev); -static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, +static void ne2k_pci_reset_8390(struct net_device *dev); +static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); -static void ne_block_input(struct device *dev, int count, +static void ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset); -static void ne_block_output(struct device *dev, const int count, +static void ne2k_pci_block_output(struct net_device *dev, const int count, const unsigned char *buf, const int start_page); -/* No room in the standard 8390 structure for extra info we need. */ +/* There is no room in the standard 8390 structure for extra info we need, + so we build a meta/outer-wrapper structure.. */ struct ne2k_pci_card { struct ne2k_pci_card *next; - struct device *dev; - unsigned char pci_bus, pci_device_fn; + struct net_device *dev; + struct pci_dev *pci_dev; }; /* A list of all installed devices, for removing the driver module. */ static struct ne2k_pci_card *ne2k_card_list = NULL; #ifdef LOAD_8390_BY_KERNELD -static int (*Lethdev_init)(struct device *dev); -static void (*LNS8390_init)(struct device *dev, int startp); -static int (*Lei_open)(struct device *dev); -static int (*Lei_close)(struct device *dev); +static int (*Lethdev_init)(struct net_device *dev); +static void (*LNS8390_init)(struct net_device *dev, int startp); +static int (*Lei_open)(struct net_device *dev); +static int (*Lei_close)(struct net_device *dev); static void (*Lei_interrupt)(int irq, void *dev_id, struct pt_regs *regs); #else #define Lethdev_init ethdev_init @@ -126,23 +202,28 @@ static void (*Lei_interrupt)(int irq, void *dev_id, struct pt_regs *regs); #endif #ifdef MODULE - -int -init_module(void) +int init_module(void) { - /* We must emit version information. */ - if (debug) - printk(KERN_INFO "%s", version); + int found_cnt; - return ne2k_pci_probe(0); + if (debug) /* Emit version even if no cards detected. */ + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); + found_cnt = pci_drv_register(&ne2k_pci_drv_id, NULL); + if (found_cnt < 0) { + printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n"); + return -ENODEV; + } + lock_8390_module(); + return 0; } -void -cleanup_module(void) +void cleanup_module(void) { - struct device *dev; + struct net_device *dev; struct ne2k_pci_card *this_card; + pci_drv_unregister(&ne2k_pci_drv_id); + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (ne2k_card_list) { dev = ne2k_card_list->dev; @@ -156,131 +237,32 @@ cleanup_module(void) #ifdef LOAD_8390_BY_KERNELD release_module("8390", 0); +#else + unlock_8390_module(); #endif } -#endif /* MODULE */ - -/* - NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet - buffer memory space. By-the-spec NE2000 clones have 0x57,0x57 in bytes - 0x0e,0x0f of the SAPROM, while other supposed NE2000 clones must be - detected by their SA prefix. - - Reading the SAPROM from a word-wide card with the 8390 set in byte-wide - mode results in doubled values, which can be detected and compensated for. - - The probe is also responsible for initializing the card and filling - in the 'dev' and 'ei_status' structures. -*/ - -#ifdef HAVE_DEVLIST -struct netdev_entry netcard_drv = -{"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0}; -#endif +#else -int ne2k_pci_probe(struct device *dev) +int ne2k_pci_probe(struct net_device *dev) { - static int pci_index = 0; /* Static, for multiple calls. */ - int cards_found = 0; - int i; - - if ( ! pcibios_present()) - return -ENODEV; - - for (;pci_index < 0xff; pci_index++) { - unsigned char pci_bus, pci_device_fn; - u8 pci_irq_line; - u16 pci_command, new_command, vendor, device; - u32 pci_ioaddr; - - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); - - /* Note: some vendor IDs (RealTek) have non-NE2k cards as well. */ - for (i = 0; pci_clone_list[i].vendor != 0; i++) - if (pci_clone_list[i].vendor == vendor - && pci_clone_list[i].dev_id == device) - break; - if (pci_clone_list[i].vendor == 0) - continue; - -#ifndef MODULE - { - static unsigned version_printed = 0; - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); - } -#endif - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; - - /* Avoid already found cards from previous calls */ - if (check_region(pci_ioaddr, NE_IO_EXTENT)) - continue; - - /* Activate the card: fix for brain-damaged Win98 BIOSes. */ - new_command = pci_command | PCI_COMMAND_IO; - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled this" - " NE2k clone! Updating PCI command %4.4x->%4.4x.\n", - pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); - } - - if (pci_irq_line <= 0 || pci_irq_line >= NR_IRQS) - printk(KERN_WARNING " WARNING: The PCI BIOS assigned this PCI NE2k" - " card to IRQ %d, which is unlikely to work!.\n" - KERN_WARNING " You should use the PCI BIOS setup to assign" - " a valid IRQ line.\n", pci_irq_line); - - printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#x, IRQ %d.\n", - pci_clone_list[i].name, pci_ioaddr, pci_irq_line); - dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line); - if (dev == 0) { - /* Should not happen. */ - printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#x failed.\n", - pci_ioaddr); - continue; - } else { - struct ne2k_pci_card *ne2k_card = - kmalloc(sizeof(struct ne2k_pci_card), GFP_KERNEL); - ne2k_card->next = ne2k_card_list; - ne2k_card_list = ne2k_card; - ne2k_card->dev = dev; - ne2k_card->pci_bus = pci_bus; - ne2k_card->pci_device_fn = pci_device_fn; - } - dev = 0; - - cards_found++; - } - - return cards_found ? 0 : -ENODEV; + int found_cnt = pci_drv_register(&ne2k_pci_drv_id, NULL); + if (found_cnt >= 0 && debug) + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); + return found_cnt; } +#endif /* MODULE */ -static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq) +static void *ne2k_pci_probe1(struct pci_dev *pdev, void *init_dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt) { + struct net_device *dev; int i; unsigned char SA_prom[32]; - const char *name = NULL; int start_page, stop_page; int reg0 = inb(ioaddr); + int flags = pci_id_tbl[chip_idx].drv_flags; + struct ne2k_pci_card *ne2k_card; if (reg0 == 0xFF) return 0; @@ -300,7 +282,18 @@ static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq) } } - dev = init_etherdev(dev, 0); + dev = init_etherdev(init_dev, 0); + + if (dev == NULL) + return 0; + ne2k_card = kmalloc(sizeof(struct ne2k_pci_card), GFP_KERNEL); + if (ne2k_card == NULL) + return 0; + + ne2k_card->next = ne2k_card_list; + ne2k_card_list = ne2k_card; + ne2k_card->dev = dev; + ne2k_card->pci_dev = pdev; /* Reset card. Who knows what dain-bramaged state it was left in. */ { @@ -363,34 +356,23 @@ static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq) } -#ifdef notdef - /* Some broken PCI cards don't respect the byte-wide - request in program_seq above, and hence don't have doubled up values. - */ - for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { - SA_prom[i] = inb(ioaddr + NE_DATAPORT); - SA_prom[i+1] = inb(ioaddr + NE_DATAPORT); - if (SA_prom[i] != SA_prom[i+1]) - sa_prom_doubled = 0; - } - - if (sa_prom_doubled) - for (i = 0; i < 16; i++) - SA_prom[i] = SA_prom[i+i]; -#else - for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) - SA_prom[i] = inb(ioaddr + NE_DATAPORT); + /* Note: all PCI cards have at least 16 bit access, so we don't have + to check for 8 bit cards. Most cards permit 32 bit access. */ -#endif + if (flags & ONLY_32BIT_IO) { + for (i = 0; i < 8; i++) + ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); + } else + for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) + SA_prom[i] = inb(ioaddr + NE_DATAPORT); /* We always set the 8390 registers for word mode. */ outb(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; - /* Set up the rest of the parameters. */ - name = "PCI NE2000"; + stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; + /* Set up the rest of the parameters. */ dev->irq = irq; dev->base_addr = ioaddr; @@ -402,17 +384,24 @@ static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq) request_region(ioaddr, NE_IO_EXTENT, dev->name); - printk("%s: %s found at %#x, IRQ %d, ", - dev->name, name, ioaddr, dev->irq); + printk("%s: %s found at %#lx, IRQ %d, ", + dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); for(i = 0; i < 6; i++) { printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":"); dev->dev_addr[i] = SA_prom[i]; } - ei_status.name = name; + ei_status.name = pci_id_tbl[chip_idx].name; ei_status.tx_start_page = start_page; ei_status.stop_page = stop_page; ei_status.word16 = 1; + ei_status.ne2k_flags = flags; + if (fnd_cnt < MAX_UNITS) { + if (full_duplex[fnd_cnt] > 0 || (options[fnd_cnt] & FORCE_FDX)) { + printk("%s: Full duplex set by user option.\n", dev->name); + ei_status.ne2k_flags |= FORCE_FDX; + } + } ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE @@ -420,28 +409,37 @@ static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq) ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; #endif - ei_status.reset_8390 = &ne_reset_8390; - ei_status.block_input = &ne_block_input; - ei_status.block_output = &ne_block_output; - ei_status.get_8390_hdr = &ne_get_8390_hdr; - dev->open = &ne_open; - dev->stop = &ne_close; + ei_status.reset_8390 = &ne2k_pci_reset_8390; + ei_status.block_input = &ne2k_pci_block_input; + ei_status.block_output = &ne2k_pci_block_output; + ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr; + dev->open = &ne2k_pci_open; + dev->stop = &ne2k_pci_close; LNS8390_init(dev, 0); return dev; } -static int -ne_open(struct device *dev) +static int ne2k_pci_open(struct net_device *dev) { - if (request_irq(dev->irq, Lei_interrupt, SA_SHIRQ, dev->name, dev)) + MOD_INC_USE_COUNT; + if (request_irq(dev->irq, Lei_interrupt, SA_SHIRQ, dev->name, dev)) { + MOD_DEC_USE_COUNT; return -EAGAIN; + } + /* Set full duplex for the chips that we know about. */ + if (ei_status.ne2k_flags & FORCE_FDX) { + long ioaddr = dev->base_addr; + if (ei_status.ne2k_flags & REALTEK_FDX) { + outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */ + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } else if (ei_status.ne2k_flags & HOLTEK_FDX) + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } Lei_open(dev); - MOD_INC_USE_COUNT; return 0; } -static int -ne_close(struct device *dev) +static int ne2k_pci_close(struct net_device *dev) { Lei_close(dev); free_irq(dev->irq, dev); @@ -451,8 +449,7 @@ ne_close(struct device *dev) /* Hard reset the card. This used to pause for the same period that a 8390 reset command required, but that shouldn't be necessary. */ -static void -ne_reset_8390(struct device *dev) +static void ne2k_pci_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; @@ -467,7 +464,7 @@ ne_reset_8390(struct device *dev) /* This check _should_not_ be necessary, omit eventually. */ while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2) { - printk("%s: ne_reset_8390() did not complete.\n", dev->name); + printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name); break; } outb(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ @@ -477,18 +474,18 @@ ne_reset_8390(struct device *dev) we don't need to be concerned with ring wrap as the header will be at the start of a page, so we optimize accordingly. */ -static void -ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) +static void ne2k_pci_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, int ring_page) { - int nic_base = dev->base_addr; + long nic_base = dev->base_addr; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_get_8390_hdr " + printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr " "[DMAstat:%d][irqlock:%d][intr:%d].\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } @@ -500,11 +497,12 @@ ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) outb(ring_page, nic_base + EN0_RSARHI); outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - *(u32*)hdr = inl(NE_BASE + NE_DATAPORT); -#else - insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); -#endif + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); + } else { + *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT)); + le16_to_cpus(&hdr->count); + } outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ ei_status.dmaing &= ~0x01; @@ -515,21 +513,23 @@ ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) The NEx000 doesn't share the on-board packet memory -- you have to put the packet out through the "remote DMA" dataport using outb. */ -static void -ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset) +static void ne2k_pci_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { - int nic_base = dev->base_addr; + long nic_base = dev->base_addr; char *buf = skb->data; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_input " + printk("%s: DMAing conflict in ne2k_pci_block_input " "[DMAstat:%d][irqlock:%d][intr:%d].\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } ei_status.dmaing |= 0x01; + if (ei_status.ne2k_flags & ONLY_32BIT_IO) + count = (count + 3) & 0xFFFC; outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); outb(count & 0xff, nic_base + EN0_RCNTLO); outb(count >> 8, nic_base + EN0_RCNTHI); @@ -537,30 +537,30 @@ ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offs outb(ring_offset >> 8, nic_base + EN0_RSARHI); outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - insl(NE_BASE + NE_DATAPORT, buf, count>>2); - if (count & 3) { - buf += count & ~3; - if (count & 2) { - *((u16 *) buf) = inw(NE_BASE + NE_DATAPORT); - buf = (void *) buf + sizeof (u16); + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + insw(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) { + buf[count-1] = inb(NE_BASE + NE_DATAPORT); + } + } else { + insl(NE_BASE + NE_DATAPORT, buf, count>>2); + if (count & 3) { + buf += count & ~3; + if (count & 2) { + *((u16 *) buf) = le16_to_cpu(inw(NE_BASE + NE_DATAPORT)); + buf = (void *) buf + sizeof (u16); + } + if (count & 1) + *buf = inb(NE_BASE + NE_DATAPORT); } - if (count & 1) - *buf = inb(NE_BASE + NE_DATAPORT); - } -#else - insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) { - buf[count-1] = inb(NE_BASE + NE_DATAPORT); } -#endif outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ ei_status.dmaing &= ~0x01; } static void -ne_block_output(struct device *dev, int count, +ne2k_pci_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page) { int nic_base = NE_BASE; @@ -568,15 +568,18 @@ ne_block_output(struct device *dev, int count, /* On little-endian it's always safe to round the count up for word writes. */ - if (count & 0x01) - count++; + if (ei_status.ne2k_flags & ONLY_32BIT_IO) + count = (count + 3) & 0xFFFC; + else + if (count & 0x01) + count++; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { - printk("%s: DMAing conflict in ne_block_output." + printk("%s: DMAing conflict in ne2k_pci_block_output." "[DMAstat:%d][irqlock:%d][intr:%d]\n", dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + (int)dev->interrupt); return; } ei_status.dmaing |= 0x01; @@ -602,26 +605,25 @@ ne_block_output(struct device *dev, int count, outb(0x00, nic_base + EN0_RSARLO); outb(start_page, nic_base + EN0_RSARHI); outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); -#if defined(USE_LONGIO) - outsl(NE_BASE + NE_DATAPORT, buf, count>>2); - if (count & 3) { - buf += count & ~3; - if (count & 2) { - outw(*((u16 *) buf), NE_BASE + NE_DATAPORT); - buf = (void *) buf + sizeof (u16); + if (ei_status.ne2k_flags & ONLY_16BIT_IO) { + outsw(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + outsl(NE_BASE + NE_DATAPORT, buf, count>>2); + if (count & 3) { + buf += count & ~3; + if (count & 2) { + outw(cpu_to_le16(*((u16 *) buf)), NE_BASE + NE_DATAPORT); + buf = (void *) buf + sizeof (u16); + } } - } -#else - outsw(NE_BASE + NE_DATAPORT, buf, count>>1); -#endif dma_start = jiffies; while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ printk("%s: timeout waiting for Tx RDC.\n", dev->name); - ne_reset_8390(dev); + ne2k_pci_reset_8390(dev); LNS8390_init(dev,1); break; } @@ -634,8 +636,8 @@ ne_block_output(struct device *dev, int count, /* * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" + * compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c ne2k-pci.c -I/usr/src/linux/drivers/net/" + * alt-compile-command: "gcc -DMODULE -O6 -c ne2k-pci.c" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 |