From: Signed-off-by: Hayato Fujiwara Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton --- /dev/null | 6238 ------------------------------------- 25-akpm/arch/m32r/drivers/Kconfig | 8 25-akpm/arch/m32r/drivers/Makefile | 2 3 files changed, 6248 deletions(-) diff -L arch/m32r/drivers/8390.c -puN arch/m32r/drivers/8390.c~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/8390.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1 +0,0 @@ -#include "../../../drivers/net/8390.c" diff -L arch/m32r/drivers/8390.h -puN arch/m32r/drivers/8390.h~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/8390.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1 +0,0 @@ -#include "../../../drivers/net/8390.h" diff -puN arch/m32r/drivers/Kconfig~m32r-remove-network-drivers arch/m32r/drivers/Kconfig --- 25/arch/m32r/drivers/Kconfig~m32r-remove-network-drivers 2004-09-15 20:19:26.523416712 -0700 +++ 25-akpm/arch/m32r/drivers/Kconfig 2004-09-15 20:19:26.530415648 -0700 @@ -9,10 +9,6 @@ config M32RPCC bool "M32R PCMCIA I/F" depends on CHIP_M32700 -config M32R_NE2000 - bool "On board NE2000 Network Interface Chip" - depends on PLAT_MAPPI || PLAT_OAKS32R - config M32R_CFC bool "CF I/F Controller" depends on PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT @@ -31,10 +27,6 @@ config MTD_M32R bool "Flash device mapped on M32R" depends on PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 -config M32R_SMC91111 - bool "On board SMC91111 Network Interface Chip" - depends on PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT - config M32700UT_DS1302 bool "DS1302 Real Time Clock support" depends on PLAT_M32700UT || PLAT_OPSPUT diff -puN arch/m32r/drivers/Makefile~m32r-remove-network-drivers arch/m32r/drivers/Makefile --- 25/arch/m32r/drivers/Makefile~m32r-remove-network-drivers 2004-09-15 20:19:26.525416408 -0700 +++ 25-akpm/arch/m32r/drivers/Makefile 2004-09-15 20:19:26.530415648 -0700 @@ -2,8 +2,6 @@ # Makefile for the Linux/M32R driver # -obj-$(CONFIG_M32R_SMC91111) += smc91111.o -obj-$(CONFIG_M32R_NE2000) += mappi_ne.o 8390.o obj-$(CONFIG_M32RPCC) += m32r_pcc.o obj-$(CONFIG_M32R_CFC) += m32r_cfc.o obj-$(CONFIG_M32700UT_DS1302) += ds1302.o diff -L arch/m32r/drivers/mappi_ne.c -puN arch/m32r/drivers/mappi_ne.c~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/mappi_ne.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,861 +0,0 @@ -/* mappi_ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ -/* - Written 1992-94 by Donald Becker. - - Copyright 1993 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 General Public License, incorporated herein by reference. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 - - This driver should work with many programmed-I/O 8390-based ethernet - boards. Currently it supports the NE1000, NE2000, many clones, - and some Cabletron products. - - Changelog: - - Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made - sanity checks and bad clone support optional. - Paul Gortmaker : new reset code, reset card after probe at boot. - Paul Gortmaker : multiple card support for module users. - Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c - Paul Gortmaker : Allow users with bad cards to avoid full probe. - Paul Gortmaker : PCI probe changes, more PCI cards supported. - rjohnson@analogic.com : Changed init order so an interrupt will only - occur after memory is allocated for dev->priv. Deallocated memory - last in cleanup_modue() - Richard Guenther : Added support for ISAPnP cards - Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead. - -*/ - -/* Routines for the NatSemi-based designs (NE[12]000). */ - -static const char version1[] = -"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n"; -static const char version2[] = -"Last modified Nov 1, 2000 by Paul Gortmaker\n"; - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "8390.h" - -/* Some defines that people can play with if so inclined. */ - -/* Do we support clones that don't adhere to 14,15 of the SAprom ? */ -#define SUPPORT_NE_BAD_CLONES - -/* Do we perform extra sanity checks on stuff ? */ -/* #define NE_SANITY_CHECK */ - -/* Do we implement the read before write bugfix ? */ -/* #define NE_RW_BUGFIX */ - -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ - -/* A zero-terminated list of I/O addresses to be probed at boot. */ -#ifndef MODULE -static unsigned int netcard_portlist[] __initdata = { - 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0 -}; -#endif - -static struct isapnp_device_id isapnp_clone_list[] __initdata = { - { ISAPNP_CARD_ID('A','X','E',0x2011), - ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011), - (long) "NetGear EA201" }, - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216), - (long) "NN NE2000" }, - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6), - (long) "Generic PNP" }, - { } /* terminate list */ -}; - -MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list); - -#ifdef SUPPORT_NE_BAD_CLONES -/* A list of bad clones that we none-the-less recognize. */ -static struct { const char *name8, *name16; unsigned char SAprefix[4];} -bad_clone_list[] __initdata = { - {"DE100", "DE200", {0x00, 0xDE, 0x01,}}, - {"DE120", "DE220", {0x00, 0x80, 0xc8,}}, - {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh? */ - {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}}, - {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */ - {"NN1000", "NN2000", {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */ - {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}}, /* Outlaw 4-Dimension cards. */ - {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */ - {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */ - {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */ - {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */ - {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ - {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */ - {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */ - {0,} -}; -#endif - -/* ---- No user-serviceable parts below ---- */ - -#define NE_BASE (dev->base_addr) -#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 NE1SM_START_PG 0x20 /* First page of TX buffer */ -#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ -#define NESM_START_PG 0x40 /* First page of TX buffer */ -#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ - -static int ne_probe1(struct net_device *dev, int ioaddr); -static int ne_probe_isapnp(struct net_device *dev); - -static int ne_open(struct net_device *dev); -static int ne_close(struct net_device *dev); - -static void ne_reset_8390(struct net_device *dev); -static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, - int ring_page); -static void ne_block_input(struct net_device *dev, int count, - struct sk_buff *skb, int ring_offset); -static void ne_block_output(struct net_device *dev, const int count, - const unsigned char *buf, const int start_page); - - -/* Probe for various non-shared-memory ethercards. - - NEx000-clone boards have a Station Address PROM (SAPROM) in the packet - buffer memory space. 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. - - We use the minimum memory size for some ethercard product lines, iff we can't - distinguish models. You can increase the packet buffer size by setting - PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are: - E1010 starts at 0x100 and ends at 0x2000. - E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") - E2010 starts at 0x100 and ends at 0x4000. - E2010-x starts at 0x100 and ends at 0xffff. */ - -static int __init do_ne_probe(struct net_device *dev) -{ - unsigned int base_addr = dev->base_addr; -#ifndef MODULE - int orig_irq = dev->irq; -#endif - - SET_MODULE_OWNER(dev); - - /* First check any supplied i/o locations. User knows best. */ - if (base_addr > 0x1ff) /* Check a single specified location. */ - return ne_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - /* Then look for any installed ISAPnP clones */ - if (isapnp_present() && (ne_probe_isapnp(dev) == 0)) - return 0; - -#ifndef MODULE - /* Last resort. The semi-risky ISA auto-probe. */ - for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) { - int ioaddr = netcard_portlist[base_addr]; - dev->irq = orig_irq; - if (ne_probe1(dev, ioaddr) == 0) - return 0; - } -#endif - - return -ENODEV; -} - -static void cleanup_card(struct net_device *dev) -{ - struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv; - if (idev) - pnp_device_detach(idev); - free_irq(dev->irq, dev); - release_region(dev->base_addr, NE_IO_EXTENT); -} - -struct net_device * __init ne_probe(int unit) -{ - struct net_device *dev = alloc_ei_netdev(); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_ne_probe(dev); - if (err) - goto out; - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - cleanup_card(dev); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -static int __init ne_probe_isapnp(struct net_device *dev) -{ - int i; - - for (i = 0; isapnp_clone_list[i].vendor != 0; i++) { - struct pnp_dev *idev = NULL; - - while ((idev = pnp_find_dev(NULL, - isapnp_clone_list[i].vendor, - isapnp_clone_list[i].function, - idev))) { - /* Avoid already found cards from previous calls */ - if (pnp_device_attach(idev) < 0) - continue; - if (pnp_activate_dev(idev) < 0) { - pnp_device_detach(idev); - continue; - } - /* if no io and irq, search for next */ - if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) { - pnp_device_detach(idev); - continue; - } - /* found it */ - dev->base_addr = pnp_port_start(idev, 0); - dev->irq = pnp_irq(idev, 0); - printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", - (char *) isapnp_clone_list[i].driver_data, - dev->base_addr, dev->irq); - if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); - pnp_device_detach(idev); - return -ENXIO; - } - ei_status.priv = (unsigned long)idev; - break; - } - if (!idev) - continue; - return 0; - } - - return -ENODEV; -} - -static int __init ne_probe1(struct net_device *dev, int ioaddr) -{ - int i; - unsigned char SA_prom[32]; - int wordlength = 2; - const char *name = NULL; - int start_page, stop_page; - int neX000, ctron, copam, bad_card; - int reg0, ret; - static unsigned version_printed; - - if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) - return -EBUSY; - - reg0 = inb_p(ioaddr); - if (reg0 == 0xFF) { - ret = -ENODEV; - goto err_out; - } - - /* Do a preliminary verification that we have a 8390. */ - { - int regd; - outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); - regd = inb_p(ioaddr + 0x0d); - outb_p(0xff, ioaddr + 0x0d); - outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); - inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ - if (inb_p(ioaddr + EN0_COUNTER0) != 0) { - outb_p(reg0, ioaddr); - outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */ - ret = -ENODEV; - goto err_out; - } - } - - if (ei_debug && version_printed++ == 0) - printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); - - printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr); - - /* A user with a poor card that fails to ack the reset, or that - does not have a valid 0x57,0x57 signature can still use this - without having to recompile. Specifying an i/o address along - with an otherwise unused dev->mem_end value of "0xBAD" will - cause the driver to skip these parts of the probe. */ - - bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad)); - - /* Reset card. Who knows what dain-bramaged state it was left in. */ - - { - unsigned long reset_start_time = jiffies; - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); - - while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - if (bad_card) { - printk(" (warning: no reset ack)"); - break; - } else { - printk(" not found (no reset ack).\n"); - ret = -ENODEV; - goto err_out; - } - } - - outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ - } - - /* Read the 16 bytes of station address PROM. - We must first initialize registers, similar to NS8390_init(eifdev, 0). - We can't reliably read the SAPROM address without this. - (I learned the hard way!). */ - { - struct {unsigned char value, offset; } program_seq[] = - { - {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ - {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ - {0x00, EN0_RCNTLO}, /* Clear the count regs. */ - {0x00, EN0_RCNTHI}, - {0x00, EN0_IMR}, /* Mask completion irq. */ - {0xFF, EN0_ISR}, - {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ - {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ - {32, EN0_RCNTLO}, - {0x00, EN0_RCNTHI}, - {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ - {0x00, EN0_RSARHI}, - {E8390_RREAD+E8390_START, E8390_CMD}, - }; - - for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) - outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); - - } - 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]) - wordlength = 1; - } - - if (wordlength == 2) - { - for (i = 0; i < 16; i++) - SA_prom[i] = SA_prom[i+i]; - /* We must set the 8390 for word mode. */ -#ifdef CONFIG_PLAT_MAPPI - outb_p(0x4b, ioaddr + EN0_DCFG); -#elif CONFIG_PLAT_OAKS32R - outb_p(0x48, ioaddr + EN0_DCFG); -#else - outb_p(0x49, ioaddr + EN0_DCFG); -#endif - start_page = NESM_START_PG; - stop_page = NESM_STOP_PG; - } else { - start_page = NE1SM_START_PG; - stop_page = NE1SM_STOP_PG; - } - -#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R) - neX000 = ((SA_prom[14] == 0x57 && SA_prom[15] == 0x57) - || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42)); -#else - neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); -#endif - ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); - copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00); - - /* Set up the rest of the parameters. */ - if (neX000 || bad_card || copam) { - name = (wordlength == 2) ? "NE2000" : "NE1000"; - } - else if (ctron) - { - name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; - start_page = 0x01; - stop_page = (wordlength == 2) ? 0x40 : 0x20; - } - else - { -#ifdef SUPPORT_NE_BAD_CLONES - /* Ack! Well, there might be a *bad* NE*000 clone there. - Check for total bogus addresses. */ - for (i = 0; bad_clone_list[i].name8; i++) - { - if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && - SA_prom[1] == bad_clone_list[i].SAprefix[1] && - SA_prom[2] == bad_clone_list[i].SAprefix[2]) - { - if (wordlength == 2) - { - name = bad_clone_list[i].name16; - } else { - name = bad_clone_list[i].name8; - } - break; - } - } - if (bad_clone_list[i].name8 == NULL) - { - printk(" not found (invalid signature %2.2x %2.2x).\n", - SA_prom[14], SA_prom[15]); - ret = -ENXIO; - goto err_out; - } -#else - printk(" not found.\n"); - ret = -ENXIO; - goto err_out; -#endif - } - - if (dev->irq < 2) - { - unsigned long cookie = probe_irq_on(); - outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ - outb_p(0x00, ioaddr + EN0_RCNTLO); - outb_p(0x00, ioaddr + EN0_RCNTHI); - outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ - mdelay(10); /* wait 10ms for interrupt to propagate */ - outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ - dev->irq = probe_irq_off(cookie); - if (ei_debug > 2) - printk(" autoirq is %d\n", dev->irq); - } else if (dev->irq == 2) - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - or don't know which one to set. */ - dev->irq = 9; - - if (! dev->irq) { - printk(" failed to detect IRQ line.\n"); - ret = -EAGAIN; - goto err_out; - } - - /* Snarf the interrupt now. There's no point in waiting since we cannot - share and the board will usually be enabled. */ - ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); - if (ret) { - printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); - goto err_out; - } - - dev->base_addr = ioaddr; - -#ifdef CONFIG_PLAT_MAPPI - outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, - ioaddr + E8390_CMD); /* 0x61 */ - for (i = 0 ; i < ETHER_ADDR_LEN ; i++) { - dev->dev_addr[i] = SA_prom[i] - = inb_p(ioaddr + EN1_PHYS_SHIFT(i)); - printk(" %2.2x", SA_prom[i]); - } -#else - for(i = 0; i < ETHER_ADDR_LEN; i++) { - printk(" %2.2x", SA_prom[i]); - dev->dev_addr[i] = SA_prom[i]; - } -#endif - - printk("\n%s: %s found at %#x, using IRQ %d.\n", - dev->name, name, ioaddr, dev->irq); - - ei_status.name = name; - ei_status.tx_start_page = start_page; - ei_status.stop_page = stop_page; -#ifdef CONFIG_PLAT_OAKS32R - ei_status.word16 = 0; -#else - ei_status.word16 = (wordlength == 2); -#endif - - ei_status.rx_start_page = start_page + TX_PAGES; -#ifdef PACKETBUF_MEMSIZE - /* Allow the packet buffer size to be overridden by know-it-alls. */ - 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; - ei_status.priv = 0; - dev->open = &ne_open; - dev->stop = &ne_close; - NS8390_init(dev, 0); - return 0; - -err_out: - release_region(ioaddr, NE_IO_EXTENT); - return ret; -} - -static int ne_open(struct net_device *dev) -{ - ei_open(dev); - return 0; -} - -static int ne_close(struct net_device *dev) -{ - if (ei_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); - return 0; -} - -/* 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 net_device *dev) -{ - unsigned long reset_start_time = jiffies; - - if (ei_debug > 1) - printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); - - /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ - outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); - - ei_status.txing = 0; - ei_status.dmaing = 0; - - /* This check _should_not_ be necessary, omit eventually. */ - while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) - if (jiffies - reset_start_time > 2*HZ/100) { - printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); - break; - } - outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ -} - -/* Grab the 8390 specific header. Similar to the block_input routine, but - 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 net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - int 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(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - - ei_status.dmaing |= 0x01; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); - outb_p(0, nic_base + EN0_RCNTHI); - outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ - outb_p(ring_page, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - - if (ei_status.word16) - insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); - else - insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; - - le16_to_cpus(&hdr->count); -} - -/* Block input and output, similar to the Crynwr packet driver. If you - are porting to a new ethercard, look at the packet driver source for hints. - 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 net_device *dev, int count, struct sk_buff *skb, int ring_offset) -{ -#ifdef NE_SANITY_CHECK - int xfer_count = count; -#endif - int 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(KERN_EMERG "%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d].\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - ei_status.dmaing |= 0x01; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); - outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) - { - insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) - { - buf[count-1] = inb(NE_BASE + NE_DATAPORT); -#ifdef NE_SANITY_CHECK - xfer_count++; -#endif - } - } else { - insb(NE_BASE + NE_DATAPORT, buf, count); - } - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. If you see - this message you either 1) have a slightly incompatible clone - or 2) have noise/speed problems with your bus. */ - - if (ei_debug > 1) - { - /* DMA termination address check... */ - int addr, tries = 20; - do { - /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here - -- it's broken for Rx on some cards! */ - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if (((ring_offset + xfer_count) & 0xff) == low) - break; - } while (--tries > 0); - if (tries <= 0) - printk(KERN_WARNING "%s: RX transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, ring_offset + xfer_count, addr); - } -#endif - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; -} - -static void ne_block_output(struct net_device *dev, int count, - const unsigned char *buf, const int start_page) -{ - int nic_base = NE_BASE; - unsigned long dma_start; -#ifdef NE_SANITY_CHECK - int retries = 0; -#endif - - /* Round the count up for word writes. Do we need to do this? - What effect will an odd byte count have on the 8390? - I should check someday. */ - - if (ei_status.word16 && (count & 0x01)) - count++; - - /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) - { - printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d]\n", - dev->name, ei_status.dmaing, ei_status.irqlock); - return; - } - ei_status.dmaing |= 0x01; - /* We should already be in page 0, but to be safe... */ - outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); - -#ifdef NE_SANITY_CHECK -retry: -#endif - -#ifdef NE8390_RW_BUGFIX - /* Handle the read-before-write bug the same way as the - Crynwr packet driver -- the NatSemi method doesn't work. - Actually this doesn't always work either, but if you have - problems with your NEx000 this is better than nothing! */ - - outb_p(0x42, nic_base + EN0_RCNTLO); - outb_p(0x00, nic_base + EN0_RCNTHI); - outb_p(0x42, nic_base + EN0_RSARLO); - outb_p(0x00, nic_base + EN0_RSARHI); - outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - /* Make certain that the dummy read has occurred. */ - udelay(6); -#endif - - outb_p(ENISR_RDC, nic_base + EN0_ISR); - - /* Now the normal output. */ - outb_p(count & 0xff, nic_base + EN0_RCNTLO); - outb_p(count >> 8, nic_base + EN0_RCNTHI); - outb_p(0x00, nic_base + EN0_RSARLO); - outb_p(start_page, nic_base + EN0_RSARHI); - - outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) { - outsw(NE_BASE + NE_DATAPORT, buf, count>>1); - } else { - outsb(NE_BASE + NE_DATAPORT, buf, count); - } - - dma_start = jiffies; - -#ifdef NE_SANITY_CHECK - /* This was for the ALPHA version only, but enough people have - been encountering problems so it is still here. */ - - if (ei_debug > 1) - { - /* DMA termination address check... */ - int addr, tries = 20; - do { - int high = inb_p(nic_base + EN0_RSARHI); - int low = inb_p(nic_base + EN0_RSARLO); - addr = (high << 8) + low; - if ((start_page << 8) + count == addr) - break; - } while (--tries > 0); - - if (tries <= 0) - { - printk(KERN_WARNING "%s: Tx packet transfer address mismatch," - "%#4.4x (expected) vs. %#4.4x (actual).\n", - dev->name, (start_page << 8) + count, addr); - if (retries++ == 0) - goto retry; - } - } -#endif - - while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ - printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); - ne_reset_8390(dev); - NS8390_init(dev,1); - break; - } - - outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ - ei_status.dmaing &= ~0x01; - return; -} - - -#ifdef MODULE -#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ -static struct net_device *dev_ne[MAX_NE_CARDS]; -static int io[MAX_NE_CARDS]; -static int irq[MAX_NE_CARDS]; -static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ - -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM_DESC(io, "I/O base address(es),required"); -MODULE_PARM_DESC(irq, "IRQ number(s)"); -MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); -MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver"); -MODULE_LICENSE("GPL"); - -/* This is set up so that no ISA autoprobe takes place. We can't guarantee -that the ne2k probe is the last 8390 based probe to take place (as it -is at boot) and so the probe will get confused by any other 8390 cards. -ISA device autoprobes on a running machine are not recommended anyway. */ - -int init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_ei_netdev(); - if (!dev) - break; - dev->irq = irq[this_dev]; - dev->mem_end = bad[this_dev]; - dev->base_addr = io[this_dev]; - if (do_ne_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; - } - cleanup_card(dev); - } - free_netdev(dev); - if (found) - break; - if (io[this_dev] != 0) - printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); - else - printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); - return -ENXIO; - } - if (found) - return 0; - return -ENODEV; -} - -void cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = dev_ne[this_dev]; - if (dev) { - unregister_netdev(dev); - cleanup_card(dev); - free_netdev(dev); - } - } -} -#endif /* MODULE */ - - -/* - * Local variables: - * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" - * version-control: t - * kept-new-versions: 5 - * End: - */ diff -L arch/m32r/drivers/smc91111.c -puN arch/m32r/drivers/smc91111.c~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/smc91111.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,3894 +0,0 @@ -/*------------------------------------------------------------------------ - . smc91111.c - . This is a driver for SMSC's 91C111 single-chip Ethernet device. - . - . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - . Developed by Simple Network Magic Corporation (SNMC) - . Copyright (C) 1996 by Erik Stahlman (ES) - . - . This program is free software; you can redistribute it and/or modify - . it under the terms of the GNU General Public License as published by - . the Free Software Foundation; either version 2 of the License, or - . (at your option) any later version. - . - . This program is distributed in the hope that it will be useful, - . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - . GNU General Public License for more details. - . - . You should have received a copy of the GNU General Public License - . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - . Information contained in this file was obtained from the LAN91C111 - . manual from SMC. To get a copy, if you really want one, you can find - . information under www.smsc.com. - . - . - . "Features" of the SMC chip: - . Integrated PHY/MAC for 10/100BaseT Operation - . Supports internal and external MII - . Integrated 8K packet memory - . EEPROM interface for configuration - . - . Arguments: - . io = for the base address - . irq = for the IRQ - . nowait = 0 for normal wait states, 1 eliminates additional wait states - . - . author: - . Erik Stahlman ( erik@vt.edu ) - . Daris A Nevil ( dnevil@snmc.com ) - . Pramod B Bhardwaj (pramod.bhardwaj@smsc.com) - . - . - . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) - . - . Sources: - . o SMSC LAN91C111 databook (www.smsc.com) - . o smc9194.c by Erik Stahlman - . o skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov ) - . - . History: - . 09/24/01 Pramod B Bhardwaj, Added the changes for Kernel 2.4 - . 08/21/01 Pramod B Bhardwaj Added support for RevB of LAN91C111 - . 04/25/01 Daris A Nevil Initial public release through SMSC - . 03/16/01 Daris A Nevil Modified smc9194.c for use with LAN91C111 - . 01/14/03 Takeo Takahashi Support M32RUT-LAN(Rev.B) - . 02/25/04 Hirokazu Takata, Hayato Fujiwara, Mamoru Sakugawa - . SMP support for Linux/M32R. - ----------------------------------------------------------------------------*/ -#include -#if defined(__m32r__) -#define SMC_DEBUG 0 -#define smc_init m32r_smc_init -#endif -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_OPSPUT) -#define NO_AUTOPROBE -#endif - -// Use power-down feature of the chip -#define POWER_DOWN 0 - - -static const char version[] = - "SMSC LAN91C111 Driver (v2.0), (Linux Kernel 2.4 + Support for Odd Byte) 09/24/01 - by Pramod Bhardwaj (pramod.bhardwaj@smsc.com)\n"; - -#ifdef MODULE -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#if defined(__m32r__) -#include -#else /* Not __m32r__ */ -#include -#endif -#include -#include -#include -#include -#include -#include - -#include -#include -#include -//#include - -#include - -#ifdef CONFIG_SYSCTL -#include -#include -#endif - -#include "smc91111.h" -/*------------------------------------------------------------------------ - . - . Configuration options, for the experienced user to change. - . - -------------------------------------------------------------------------*/ - -/* - . Do you want to use 32 bit xfers? This should work on all chips, as - . the chipset is designed to accommodate them. -*/ -#if !defined(__m32r__) -#define USE_32_BIT 1 -#endif - - -/* - .the LAN91C111 can be at any of the following port addresses. To change, - .for a slightly different card, you can add it to the array. Keep in - .mind that the array must end in zero. -*/ -static unsigned int smc_portlist[] __initdata = - { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, - 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0}; - - -/* - . Wait time for memory to be free. This probably shouldn't be - . tuned that much, as waiting for this means nothing else happens - . in the system -*/ -#define MEMORY_WAIT_TIME 16 - -/* - . This selects whether TX packets are sent one by one to the SMC91x internal - . memory ans throttled until transmission completes. This may prevent - . RX overruns a litle by keeping much of the memory free for RX packets - . but to the expense of reduced TX throughput and increased IRQ overhead. - . Note this is not a cure for a too slow data bus or too high IRQ latency. - */ -#define THROTTLE_TX_PKTS 1 - -/* - . DEBUGGING LEVELS - . - . 0 for normal operation - . 1 for slightly more details - . >2 for various levels of increasingly useless information - . 2 for interrupt tracking, status flags - . 3 for packet info - . 4 for complete packet dumps -*/ -//#define SMC_DEBUG 3 // Must be defined in makefile - -#if (SMC_DEBUG > 2 ) -#define PRINTK3(args...) printk(args) -#else -#define PRINTK3(args...) -#endif - -#if SMC_DEBUG > 1 -#define PRINTK2(args...) printk(args) -#else -#define PRINTK2(args...) -#endif - -#ifdef SMC_DEBUG -#define PRINTK(args...) printk(args) -#else -#define PRINTK(args...) -#endif - - -/*------------------------------------------------------------------------ - . - . The internal workings of the driver. If you are changing anything - . here with the SMC stuff, you should have the datasheet and know - . what you are doing. - . - -------------------------------------------------------------------------*/ -#define CARDNAME "LAN91C111" - -// Memory sizing constant -#define LAN91C111_MEMORY_MULTIPLIER (1024*2) - -/* store this information for the driver.. */ -struct smc_local { - - // these are things that the kernel wants me to keep, so users - // can find out semi-useless statistics of how well the card is - // performing - struct net_device_stats stats; - - // If I have to wait until memory is available to send - // a packet, I will store the skbuff here, until I get the - // desired memory. Then, I'll send it out and free it. - struct sk_buff * saved_skb; - - // This keeps track of how many packets that I have - // sent out. When an TX_EMPTY interrupt comes, I know - // that all of these have been sent. - int packets_waiting; - - // Set to true during the auto-negotiation sequence - int autoneg_active; - - // Address of our PHY port - word phyaddr; - - // Type of PHY - word phytype; - - // Last contents of PHY Register 18 - word lastPhy18; - - // Contains the current active transmission mode - word tcr_cur_mode; - - // Contains the current active receive mode - word rcr_cur_mode; - - // Contains the current active receive/phy mode - word rpc_cur_mode; - - /* => Pramod, Odd Byte issue */ - // Contains the Current ChipID - unsigned short ChipID; - - //Contains the Current ChipRevision - unsigned short ChipRev; - /* <= Pramod, Odd Byte issue */ - - spinlock_t lock; - -#ifdef CONFIG_SYSCTL - - // Root directory /proc/sys/dev - // Second entry must be null to terminate the table - ctl_table root_table[2]; - - // Directory for this device /proc/sys/dev/ethX - // Again the second entry must be zero to terminate - ctl_table eth_table[2]; - - // This is the parameters (file) table - ctl_table param_table[CTL_SMC_LAST_ENTRY]; - - // Saves the sysctl header returned by register_sysctl_table() - // we send this to unregister_sysctl_table() - struct ctl_table_header *sysctl_header; - - // Parameter variables (files) go here - char ctl_info[1024]; - int ctl_swfdup; - int ctl_ephloop; - int ctl_miiop; - int ctl_autoneg; - int ctl_rfduplx; - int ctl_rspeed; - int ctl_afduplx; - int ctl_aspeed; - int ctl_lnkfail; - int ctl_forcol; - int ctl_filtcar; - int ctl_freemem; - int ctl_totmem; - int ctl_leda; - int ctl_ledb; - int ctl_chiprev; -#ifdef SMC_DEBUG - int ctl_reg_bsr; - int ctl_reg_tcr; - int ctl_reg_esr; - int ctl_reg_rcr; - int ctl_reg_ctrr; - int ctl_reg_mir; - int ctl_reg_rpcr; - int ctl_reg_cfgr; - int ctl_reg_bar; - int ctl_reg_iar0; - int ctl_reg_iar1; - int ctl_reg_iar2; - int ctl_reg_gpr; - int ctl_reg_ctlr; - int ctl_reg_mcr; - int ctl_reg_pnr; - int ctl_reg_fpr; - int ctl_reg_ptr; - int ctl_reg_dr; - int ctl_reg_isr; - int ctl_reg_mtr1; - int ctl_reg_mtr2; - int ctl_reg_mtr3; - int ctl_reg_mtr4; - int ctl_reg_miir; - int ctl_reg_revr; - int ctl_reg_ercvr; - int ctl_reg_extr; - int ctl_phy_ctrl; - int ctl_phy_stat; - int ctl_phy_id1; - int ctl_phy_id2; - int ctl_phy_adc; - int ctl_phy_remc; - int ctl_phy_cfg1; - int ctl_phy_cfg2; - int ctl_phy_int; - int ctl_phy_mask; -#endif // SMC_DEBUG - - -#endif // CONFIG_SYSCTL - -}; - - -/*----------------------------------------------------------------- - . - . The driver can be entered at any of the following entry points. - . - .------------------------------------------------------------------ */ - -/* - . This is called by register_netdev(). It is responsible for - . checking the portlist for the SMC9000 series chipset. If it finds - . one, then it will initialize the device, find the hardware information, - . and sets up the appropriate device parameters. - . NOTE: Interrupts are *OFF* when this procedure is called. - . - . NB:This shouldn't be static since it is referred to externally. -*/ -struct net_device *smc_init(int unit); - -/* - . This is called by unregister_netdev(). It is responsible for - . cleaning up before the driver is finally unregistered and discarded. -*/ -void smc_destructor(struct net_device *dev); - -/* - . The kernel calls this function when someone wants to use the net_device, - . typically 'ifconfig ethX up'. -*/ -static int smc_open(struct net_device *dev); - -/* - . This is called by the kernel to send a packet out into the net. it's - . responsible for doing a best-effort send, but if it's simply not possible - . to send it, the packet gets dropped. -*/ -static void smc_timeout (struct net_device *dev); -/* - . This is called by the kernel in response to 'ifconfig ethX down'. It - . is responsible for cleaning up everything that the open routine - . does, and maybe putting the card into a powerdown state. -*/ -static int smc_close(struct net_device *dev); - -/* - . This routine allows the proc file system to query the driver's - . statistics. -*/ -static struct net_device_stats * smc_query_statistics( struct net_device *dev); - -/* - . Finally, a call to set promiscuous mode ( for TCPDUMP and related - . programs ) and multicast modes. -*/ -static void smc_set_multicast_list(struct net_device *dev); - -/* - . Configures the PHY through the MII Management interface -*/ -static void smc_phy_configure(struct net_device* dev); - -/*--------------------------------------------------------------- - . - . Interrupt level calls.. - . - ----------------------------------------------------------------*/ - -/* - . Handles the actual interrupt -*/ -static irqreturn_t smc_interrupt(int irq, void *, struct pt_regs *regs); -/* - . This is a separate procedure to handle the receipt of a packet, to - . leave the interrupt code looking slightly cleaner -*/ -static inline void smc_rcv( struct net_device *dev ); -/* - . This handles a TX interrupt, which is only called when an error - . relating to a packet is sent. -*/ -static inline void smc_tx( struct net_device * dev ); - -/* - . This handles interrupts generated from PHY register 18 -*/ -static void smc_phy_interrupt(struct net_device* dev); - -/* - ------------------------------------------------------------ - . - . Internal routines - . - ------------------------------------------------------------ -*/ - -/* - . Test if a given location contains a chip, trying to cause as - . little damage as possible if it's not a SMC chip. -*/ -static int smc_probe(struct net_device *dev, int ioaddr); - -/* - . A rather simple routine to print out a packet for debugging purposes. -*/ -#if SMC_DEBUG > 2 -static void print_packet( byte *, int ); -#endif - -#define tx_done(dev) 1 - -/* this is called to actually send the packet to the chip */ -static void smc_hardware_send_packet( struct net_device * dev ); - -/* Since I am not sure if I will have enough room in the chip's ram - . to store the packet, I call this routine, which either sends it - . now, or generates an interrupt when the card is ready for the - . packet */ -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev ); - -/* this does a soft reset on the device */ -static void smc_reset( struct net_device* dev ); - -/* Enable Interrupts, Receive, and Transmit */ -static void smc_enable( struct net_device *dev ); - -/* this puts the device in an inactive state */ -static void smc_shutdown( int ioaddr ); - -#ifndef NO_AUTOPROBE -/* This routine will find the IRQ of the driver if one is not - . specified in the input to the device. */ -static int smc_findirq( int ioaddr ); -#endif - -/* - this routine will set the hardware multicast table to the specified - values given it by the higher level routines -*/ -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * ); -static int crc32( char *, int ); - -/* Routines to Read and Write the PHY Registers across the - MII Management Interface -*/ - -static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg); -static void smc_write_phy_register(int ioaddr, byte phyaddr, byte phyreg, word phydata); - -/* Initilizes our device's sysctl proc filesystem */ - -#ifdef CONFIG_SYSCTL -static void smc_sysctl_register(struct net_device *); -static void smc_sysctl_unregister(struct net_device *); -#endif /* CONFIG_SYSCTL */ - -/* - . Function: smc_reset( struct device* dev ) - . Purpose: - . This sets the SMC91111 chip to its normal state, hopefully from whatever - . mess that any other DOS driver has put it in. - . - . Maybe I should reset more registers to defaults in here? SOFTRST should - . do that for me. - . - . Method: - . 1. send a SOFT RESET - . 2. wait for it to finish - . 3. enable autorelease mode - . 4. reset the memory management unit - . 5. clear all interrupts - . -*/ -static void smc_reset( struct net_device* dev ) -{ - //struct smc_local *lp = (struct smc_local *)dev->priv; - int ioaddr = dev->base_addr; - - PRINTK2("%s:smc_reset\n", dev->name); - - /* This resets the registers mostly to defaults, but doesn't - affect EEPROM. That seems unnecessary */ - SMC_SELECT_BANK( 0 ); - outw( RCR_SOFTRST, ioaddr + RCR_REG ); - - /* Setup the Configuration Register */ - /* This is necessary because the CONFIG_REG is not affected */ - /* by a soft reset */ - - SMC_SELECT_BANK( 1 ); - outw( CONFIG_DEFAULT, ioaddr + CONFIG_REG); - - /* Setup for fast accesses if requested */ - /* If the card/system can't handle it then there will */ - /* be no recovery except for a hard reset or power cycle */ - - if (dev->dma) - outw( inw( ioaddr + CONFIG_REG ) | CONFIG_NO_WAIT, - ioaddr + CONFIG_REG ); - -#ifdef POWER_DOWN - /* Release from possible power-down state */ - /* Configuration register is not affected by Soft Reset */ - SMC_SELECT_BANK( 1 ); - outw( inw( ioaddr + CONFIG_REG ) | CONFIG_EPH_POWER_EN, - ioaddr + CONFIG_REG ); -#endif - - SMC_SELECT_BANK( 0 ); - - /* this should pause enough for the chip to be happy */ - mdelay(10); - - /* Disable transmit and receive functionality */ - outw( RCR_CLEAR, ioaddr + RCR_REG ); - outw( TCR_CLEAR, ioaddr + TCR_REG ); - - /* set the control register to automatically - release successfully transmitted packets, to make the best - use out of our limited memory */ - SMC_SELECT_BANK( 1 ); -#if ! THROTTLE_TX_PKTS - outw( inw( ioaddr + CTL_REG ) | CTL_AUTO_RELEASE , ioaddr + CTL_REG ); -#else - outw( inw( ioaddr + CTL_REG ) & ~CTL_AUTO_RELEASE , ioaddr + CTL_REG ); -#endif - - /* Reset the MMU */ - SMC_SELECT_BANK( 2 ); - outw( MC_RESET, ioaddr + MMU_CMD_REG ); - - /* Note: It doesn't seem that waiting for the MMU busy is needed here, - but this is a place where future chipsets _COULD_ break. Be wary - of issuing another MMU command right after this */ - - /* Disable all interrupts */ - outb( 0, ioaddr + IM_REG ); -} - -/* - . Function: smc_enable - . Purpose: let the chip talk to the outside work - . Method: - . 1. Enable the transmitter - . 2. Enable the receiver - . 3. Enable interrupts -*/ -static void smc_enable( struct net_device *dev ) -{ - unsigned short ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - - PRINTK2("%s:smc_enable\n", dev->name); - - SMC_SELECT_BANK( 0 ); - /* see the header file for options in TCR/RCR DEFAULT*/ - outw( lp->tcr_cur_mode, ioaddr + TCR_REG ); - outw( lp->rcr_cur_mode, ioaddr + RCR_REG ); - - /* now, enable interrupts */ - SMC_SELECT_BANK( 2 ); - outb( SMC_INTERRUPT_MASK, ioaddr + IM_REG ); -} - -/* - . Function: smc_shutdown - . Purpose: closes down the SMC91xxx chip. - . Method: - . 1. zero the interrupt mask - . 2. clear the enable receive flag - . 3. clear the enable xmit flags - . - . TODO: - . (1) maybe utilize power down mode. - . Why not yet? Because while the chip will go into power down mode, - . the manual says that it will wake up in response to any I/O requests - . in the register space. Empirical results do not show this working. -*/ -static void smc_shutdown( int ioaddr ) -{ - PRINTK2("CARDNAME:smc_shutdown\n"); - - /* no more interrupts for me */ - SMC_SELECT_BANK( 2 ); - outb( 0, ioaddr + IM_REG ); - - /* and tell the card to stay away from that nasty outside world */ - SMC_SELECT_BANK( 0 ); - outb( RCR_CLEAR, ioaddr + RCR_REG ); - outb( TCR_CLEAR, ioaddr + TCR_REG ); - -#ifdef POWER_DOWN - /* finally, shut the chip down */ - SMC_SELECT_BANK( 1 ); - outw( inw( ioaddr + CONFIG_REG ) & ~CONFIG_EPH_POWER_EN, - ioaddr + CONFIG_REG ); -#endif -} - - -/* - . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) - . Purpose: - . This sets the internal hardware table to filter out unwanted multicast - . packets before they take up memory. - . - . The SMC chip uses a hash table where the high 6 bits of the CRC of - . address are the offset into the table. If that bit is 1, then the - . multicast packet is accepted. Otherwise, it's dropped silently. - . - . To use the 6 bits as an offset into the table, the high 3 bits are the - . number of the 8 bit register, while the low 3 bits are the bit within - . that register. - . - . This routine is based very heavily on the one provided by Peter Cammaert. -*/ - - -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) { - int i; - unsigned char multicast_table[ 8 ]; - struct dev_mc_list * cur_addr; - /* table for flipping the order of 3 bits */ - unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - - PRINTK2("CARDNAME:smc_setmulticast\n"); - - /* start with a table of all zeros: reject all */ - memset( multicast_table, 0, sizeof( multicast_table ) ); - - cur_addr = addrs; - for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { - int position; - - /* do we have a pointer here? */ - if ( !cur_addr ) - break; - /* make sure this is a multicast address - shouldn't this - be a given if we have it here ? */ - if ( !( *cur_addr->dmi_addr & 1 ) ) - continue; - - /* only use the low order bits */ - position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; - - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert3[position&7]] |= - (1<>3)&7]); - - } - /* now, the table can be loaded into the chipset */ - SMC_SELECT_BANK( 3 ); - - for ( i = 0; i < 8 ; i++ ) { - outb( multicast_table[i], ioaddr + MCAST_REG1 + i ); - } -} - -/* - Finds the CRC32 of a set of bytes. - Again, from Peter Cammaert's code. -*/ -static int crc32( char * s, int length ) { - /* indices */ - int perByte; - int perBit; - /* crc polynomial for Ethernet */ - const unsigned long poly = 0xedb88320; - /* crc value - preinitialized to all 1's */ - unsigned long crc_value = 0xffffffff; - - for ( perByte = 0; perByte < length; perByte ++ ) { - unsigned char c; - - c = *(s++); - for ( perBit = 0; perBit < 8; perBit++ ) { - crc_value = (crc_value>>1)^ - (((crc_value^c)&0x01)?poly:0); - c >>= 1; - } - } - return crc_value; -} - - -/* - . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) - . Purpose: - . Attempt to allocate memory for a packet, if chip-memory is not - . available, then tell the card to generate an interrupt when it - . is available. - . - . Algorithm: - . - . o if the saved_skb is not currently null, then drop this packet - . on the floor. This should never happen, because of TBUSY. - . o if the saved_skb is null, then replace it with the current packet, - . o See if I can sending it now. - . o (NO): Enable interrupts and let the interrupt handler deal with it. - . o (YES):Send it now. -*/ -static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev ) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - unsigned short ioaddr = dev->base_addr; - word length; - unsigned short numPages; - word time_out; - word status; - unsigned long flags; - - PRINTK3("%s:smc_wait_to_send_packet\n", dev->name); - - spin_lock_irqsave(&lp->lock, flags); - - if ( lp->saved_skb) { - /* THIS SHOULD NEVER HAPPEN. */ - lp->stats.tx_aborted_errors++; - printk("%s: Bad Craziness - sent packet while busy.\n", - dev->name); - spin_unlock_irqrestore(&lp->lock, flags); - return 1; - } - lp->saved_skb = skb; - - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - /* - ** The MMU wants the number of pages to be the number of 256 bytes - ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) - ** - ** The 91C111 ignores the size bits, but the code is left intact - ** for backwards and future compatibility. - ** - ** Pkt size for allocating is data length +6 (for additional status - ** words, length and ctl!) - ** - ** If odd size then last byte is included in this header. - */ - numPages = ((length & 0xfffe) + 6); - numPages >>= 8; // Divide by 256 - - if (numPages > 7 ) { - printk("%s: Far too big packet error. \n", dev->name); - /* freeing the packet is a good thing here... but should - . any packets of this size get down here? */ - dev_kfree_skb (skb); - lp->saved_skb = NULL; - /* this IS an error, but, i don't want the skb saved */ - netif_wake_queue(dev); - spin_unlock_irqrestore(&lp->lock, flags); - return 0; - } - /* either way, a packet is waiting now */ - lp->packets_waiting++; - - /* now, try to allocate the memory */ - SMC_SELECT_BANK( 2 ); - outw( MC_ALLOC | numPages, ioaddr + MMU_CMD_REG ); - /* - . Performance Hack - . - . wait a short amount of time.. if I can send a packet now, I send - . it now. Otherwise, I enable an interrupt and wait for one to be - . available. - . - . I could have handled this a slightly different way, by checking to - . see if any memory was available in the FREE MEMORY register. However, - . either way, I need to generate an allocation, and the allocation works - . no matter what, so I saw no point in checking free memory. - */ - time_out = MEMORY_WAIT_TIME; - do { - status = inb( ioaddr + INT_REG ); - if ( status & IM_ALLOC_INT ) { - /* acknowledge the interrupt */ - outb( IM_ALLOC_INT, ioaddr + INT_REG ); - break; - } - } while ( -- time_out ); - - if ( !time_out ) { -#if defined(__m32r__) -// netif_stop_queue(dev); // 2003-07-13 by takeo -#endif - /* oh well, wait until the chip finds memory later */ - SMC_ENABLE_INT( IM_ALLOC_INT ); - - /* Check the status bit one more time just in case */ - /* it snuk in between the time we last checked it */ - /* and when we set the interrupt bit */ - status = inb( ioaddr + INT_REG ); - if ( !(status & IM_ALLOC_INT) ) { - PRINTK2("%s: memory allocation deferred. \n", - dev->name); - /* it's deferred, but I'll handle it later */ - spin_unlock_irqrestore(&lp->lock, flags); - return 0; - } - - /* Looks like it did sneak in, so disable */ - /* the interrupt */ - SMC_DISABLE_INT( IM_ALLOC_INT ); - } - /* or YES! I can send the packet now.. */ -#if THROTTLE_TX_PKTS - netif_stop_queue(dev); -#endif - smc_hardware_send_packet(dev); -// netif_wake_queue(dev); - - spin_unlock_irqrestore(&lp->lock, flags); - - return 0; -} - -/* - . Function: smc_hardware_send_packet(struct device * ) - . Purpose: - . This sends the actual packet to the SMC9xxx chip. - . - . Algorithm: - . First, see if a saved_skb is available. - . ( this should NOT be called if there is no 'saved_skb' - . Now, find the packet number that the chip allocated - . Point the data pointers at it in memory - . Set the length word in the chip's memory - . Dump the packet to chip memory - . Check if a last byte is needed ( odd length packet ) - . if so, set the control flag right - . Tell the card to send it - . Enable the transmit interrupt, so I know if it failed - . Free the kernel data if I actually sent it. -*/ -static void smc_hardware_send_packet( struct net_device * dev ) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - byte packet_no; - struct sk_buff * skb = lp->saved_skb; - word length; - unsigned short ioaddr; - byte * buf; - - PRINTK3("%s:smc_hardware_send_packet\n", dev->name); - - ioaddr = dev->base_addr; - - if ( !skb ) { - PRINTK("%s: In XMIT with no packet to send \n", dev->name); - return; - } - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - buf = skb->data; - - /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = inb( ioaddr + AR_REG ); - if ( packet_no & AR_FAILED ) { - /* or isn't there? BAD CHIP! */ - printk(KERN_DEBUG "%s: Memory allocation failed. \n", - dev->name); - dev_kfree_skb_any (skb); - lp->saved_skb = NULL; - netif_wake_queue(dev); - return; - } - - /* we have a packet address, so tell the card to use it */ - outb( packet_no, ioaddr + PN_REG ); - - /* point to the beginning of the packet */ - outw( PTR_AUTOINC , ioaddr + PTR_REG ); - - PRINTK3("%s: Trying to xmit packet of length %x\n", - dev->name, length); - -#if SMC_DEBUG > 2 - printk("Transmitting Packet\n"); - print_packet( buf, length ); -#endif - - /* send the packet length ( +6 for status, length and ctl byte ) - and the status word ( set to zeros ) */ -#ifdef USE_32_BIT - outl( (length +6 ) << 16 , ioaddr + DATA_REG ); -#else - outw( 0, ioaddr + DATA_REG ); - /* send the packet length ( +6 for status words, length, and ctl*/ - outb( (length+6) & 0xFF,ioaddr + DATA_REG ); - outb( (length+6) >> 8 , ioaddr + DATA_REG ); -#endif - - /* send the actual data - . I _think_ it's faster to send the longs first, and then - . mop up by sending the last word. It depends heavily - . on alignment, at least on the 486. Maybe it would be - . a good idea to check which is optimal? But that could take - . almost as much time as is saved? - */ -#ifdef USE_32_BIT - outsl(ioaddr + DATA_REG, buf, length >> 2 ); - if ( length & 0x2 ) - outw(*((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_REG); -#else - outsw(ioaddr + DATA_REG , buf, (length ) >> 1); -#endif // USE_32_BIT - - /* Send the last byte, if there is one. */ - if ( (length & 1) == 0 ) { - outw( 0, ioaddr + DATA_REG ); - } else { - outb( buf[length -1 ], ioaddr + DATA_REG ); - outb( 0x20, ioaddr + DATA_REG); // Set odd bit in CONTROL BYTE - } - - /* and let the chipset deal with it */ - outw( MC_ENQUEUE , ioaddr + MMU_CMD_REG ); - - /* enable the interrupts */ - SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) ); - - PRINTK2("%s: Sent packet of length %d \n", dev->name, length); -#if defined(__m32r__) - lp->stats.tx_bytes += length; -#endif - - lp->saved_skb = NULL; - dev_kfree_skb_any (skb); - - dev->trans_start = jiffies; - - /* we can send another packet */ -// netif_wake_queue(dev); - - return; -} - -/*------------------------------------------------------------------------- - | - | smc_init( int unit ) - | Input parameters: - | dev->base_addr == 0, try to find all possible locations - | dev->base_addr == 1, return failure code - | dev->base_addr == 2, always allocate space, and return success - | dev->base_addr == this is the address to check - | - | Output: - | pointer to net_device or ERR_PTR(error) - | - --------------------------------------------------------------------------- -*/ -static int io; -static int irq; -static int ifport; - -struct net_device * __init smc_init(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct smc_local)); - unsigned int *port; - int err = 0; - - if (!dev) - return ERR_PTR(-ENODEV); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - io = dev->base_addr; - irq = dev->irq; - } - -#ifdef MODULE - SET_MODULE_OWNER (dev); -#endif - if (io > 0x1ff) { /* Check a single specified location. */ - err = smc_probe(dev, io); - } else if (io != 0) { /* Don't probe at all. */ - err = -ENXIO; - } else { - for (port = smc_portlist; *port; port++) { - if (smc_probe(dev, *port) == 0) - break; - } - if (!*port) - err = -ENODEV; - } - if (err) - goto out; - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - free_irq(dev->irq, dev); - release_region(dev->base_addr, SMC_IO_EXTENT); -out: - free_netdev(dev); - return ERR_PTR(err); -} - - -/*------------------------------------------------------------------------- - | - | smc_destructor( struct device * dev ) - | Input parameters: - | dev, pointer to the device structure - | - | Output: - | None. - | - --------------------------------------------------------------------------- -*/ -void smc_destructor(struct net_device *dev) -{ - PRINTK2("CARDNAME:smc_destructor\n"); -} - - -#ifndef NO_AUTOPROBE -/*---------------------------------------------------------------------- - . smc_findirq - . - . This routine has a simple purpose -- make the SMC chip generate an - . interrupt, so an auto-detect routine can detect it, and find the IRQ, - ------------------------------------------------------------------------ -*/ -int __init smc_findirq( int ioaddr ) -{ - int timeout = 20; - unsigned long cookie; - - PRINTK2("CARDNAME:smc_findirq\n"); - - /* I have to do a STI() here, because this is called from - a routine that does an CLI during this process, making it - rather difficult to get interrupts for auto detection */ - sti(); - - cookie = probe_irq_on(); - - /* - * What I try to do here is trigger an ALLOC_INT. This is done - * by allocating a small chunk of memory, which will give an interrupt - * when done. - */ - - - SMC_SELECT_BANK(2); - /* enable ALLOCation interrupts ONLY */ - outb( IM_ALLOC_INT, ioaddr + IM_REG ); - - /* - . Allocate 512 bytes of memory. Note that the chip was just - . reset so all the memory is available - */ - outw( MC_ALLOC | 1, ioaddr + MMU_CMD_REG ); - - /* - . Wait until positive that the interrupt has been generated - */ - while ( timeout ) { - byte int_status; - - int_status = inb( ioaddr + INT_REG ); - - if ( int_status & IM_ALLOC_INT ) - break; /* got the interrupt */ - timeout--; - } - - /* there is really nothing that I can do here if timeout fails, - as autoirq_report will return a 0 anyway, which is what I - want in this case. Plus, the clean up is needed in both - cases. */ - - /* DELAY HERE! - On a fast machine, the status might change before the interrupt - is given to the processor. This means that the interrupt was - never detected, and autoirq_report fails to report anything. - This should fix autoirq_* problems. - */ - mdelay(10); - - /* and disable all interrupts again */ - outb( 0, ioaddr + IM_REG ); - - /* clear hardware interrupts again, because that's how it - was when I was called... */ - cli(); - - /* and return what I found */ - return probe_irq_off(cookie); -} -#endif - -/*---------------------------------------------------------------------- - . Function: smc_probe( int ioaddr ) - . - . Purpose: - . Tests to see if a given ioaddr points to an SMC91111 chip. - . Returns a 0 on success - . - . Algorithm: - . (1) see if the high byte of BANK_SELECT is 0x33 - . (2) compare the ioaddr with the base register's address - . (3) see if I recognize the chip ID in the appropriate register - . - .--------------------------------------------------------------------- - */ -/*--------------------------------------------------------------- - . Here I do typical initialization tasks. - . - . o Initialize the structure if needed - . o print out my vanity message if not done so already - . o print out what type of hardware is detected - . o print out the ethernet address - . o find the IRQ - . o set up my private data - . o configure the dev structure with my subroutines - . o actually GRAB the irq. - . o GRAB the region - .-----------------------------------------------------------------*/ - -static int __init smc_probe(struct net_device *dev, int ioaddr ) -{ - int i, memory, retval; - static unsigned version_printed = 0; - unsigned int bank; - - const char *version_string; - - /*registers */ - word revision_register; - word base_address_register; - word memory_info_register; - /*=> Pramod */ - struct smc_local *lp; - /*<= Pramod */ - - PRINTK2("CARDNAME:smc_probe\n"); - - /* Grab the region so that no one else tries to probe our ioports. */ - if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) return -EBUSY; - - dev->irq = irq; - dev->if_port = ifport; - - /* First, see if the high byte is 0x33 */ - bank = inw( ioaddr + BANK_SELECT ); - if ( (bank & 0xFF00) != 0x3300 ) return -ENODEV; - - /* The above MIGHT indicate a device, but I need to write to further test this. */ - outw( 0x0, ioaddr + BANK_SELECT ); - bank = inw( ioaddr + BANK_SELECT ); - if ( (bank & 0xFF00 ) != 0x3300 ) - { - retval = -ENODEV; - goto err_out; - } - - /* well, we've already written once, so hopefully another time won't - hurt. This time, I need to switch the bank register to bank 1, - so I can access the base address register */ - SMC_SELECT_BANK(1); - base_address_register = inw( ioaddr + BASE_REG ); - if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) - { - printk("CARDNAME: IOADDR %x doesn't match configuration (%x)." - "Probably not a SMC chip\n", - ioaddr, base_address_register >> 3 & 0x3E0 ); - /* well, the base address register didn't match. Must not have - been a SMC chip after all. */ - retval = -ENODEV; - goto err_out; - } - - /* check if the revision register is something that I recognize. - These might need to be added to later, as future revisions - could be added. */ - SMC_SELECT_BANK(3); - revision_register = inw( ioaddr + REV_REG ); - if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) - { - /* I don't recognize this chip, so... */ - printk("CARDNAME: IO %x: Unrecognized revision register:" - " %x, Contact author. \n", - ioaddr, revision_register ); - retval = -ENODEV; - goto err_out; - } - - /* at this point I'll assume that the chip is an SMC9xxx. - It might be prudent to check a listing of MAC addresses - against the hardware address, or do some other tests. */ - - if (version_printed++ == 0) - printk("%s", version); - - /* fill in some of the fields */ - dev->base_addr = ioaddr; - - /* - . Get the MAC address ( bank 1, regs 4 - 9 ) - */ - SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) - { - word address; - - address = inw( ioaddr + ADDR0_REG + i ); - dev->dev_addr[ i + 1] = address >> 8; - dev->dev_addr[ i ] = address & 0xFF; - } - - /* get the memory information */ - - SMC_SELECT_BANK( 0 ); - memory_info_register = inw( ioaddr + MIR_REG ); - memory = memory_info_register & (word)0x00ff; - memory *= LAN91C111_MEMORY_MULTIPLIER; - - /* - Now, I want to find out more about the chip. This is sort of - redundant, but it's cleaner to have it in both, rather than having - one VERY long probe procedure. - */ - SMC_SELECT_BANK(3); - revision_register = inw( ioaddr + REV_REG ); - version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ]; - if ( !version_string ) - { - /* I shouldn't get here because this call was done before.... */ - retval = -ENODEV; - goto err_out; - } - - /* now, reset the chip, and put it into a known state */ - smc_reset( dev ); - - /* - . If dev->irq is 0, then the device has to be banged on to see - . what the IRQ is. - . - . This banging doesn't always detect the IRQ, for unknown reasons. - . a workaround is to reset the chip and try again. - . - . Interestingly, the DOS packet driver *SETS* the IRQ on the card to - . be what is requested on the command line. I don't do that, mostly - . because the card that I have uses a non-standard method of accessing - . the IRQs, and because this _should_ work in most configurations. - . - . Specifying an IRQ is done with the assumption that the user knows - . what (s)he is doing. No checking is done!!!! - . - */ -#if defined(CONFIG_PLAT_M32700UT) && defined(NO_AUTOPROBE) - dev->irq = M32700UT_LAN_IRQ_LAN; -#endif -#if defined(CONFIG_PLAT_OPSPUT) && defined(NO_AUTOPROBE) - dev->irq = OPSPUT_LAN_IRQ_LAN; -#endif -#ifndef NO_AUTOPROBE // by takeo - if ( dev->irq < 2 ) { - int trials; - - trials = 3; - while ( trials-- ) { - dev->irq = smc_findirq( ioaddr ); - if ( dev->irq ) - break; - /* kick the card and try again */ - smc_reset( dev ); - } - } - - if (dev->irq == 0 ) { - printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", - dev->name); - retval = -ENODEV; - goto err_out; - } - - if (dev->irq == 2) { - /* Fixup for users that don't know that IRQ 2 is really IRQ 9, - * or don't know which one to set. - */ - dev->irq = 9; - } -#endif - - /* now, print out the card info, in a short format.. */ - - printk("%s: %s(rev:%d) at %#3x IRQ:%d MEMSIZE:%db NOWAIT:%d ", - dev->name, - version_string, revision_register & 0xF, ioaddr, dev->irq, - memory, dev->dma); - /* - . Print the Ethernet address - */ - printk("ADDR: "); - for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i] ); - printk("%2.2x \n", dev->dev_addr[5] ); - - /* set the private data to zero by default */ - memset(dev->priv, 0, sizeof(struct smc_local)); - - /* Grab the IRQ */ - retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); - if (retval) { - printk("%s: unable to get IRQ %d (irqval=%d).\n", - dev->name, dev->irq, retval); - goto err_out; - } - - dev->open = smc_open; - dev->stop = smc_close; - dev->hard_start_xmit = smc_wait_to_send_packet; - dev->tx_timeout = smc_timeout; - dev->get_stats = smc_query_statistics; -#ifdef HAVE_MULTICAST - dev->set_multicast_list = &smc_set_multicast_list; -#endif - - /* => Store the ChipRevision and ChipID, to be used in resolving the Odd-Byte issue in RevB of LAN91C111; Pramod */ - SMC_SELECT_BANK(3); - revision_register = inw( ioaddr + REV_REG ); - lp = (struct smc_local *)dev->priv; - lp->ChipID = (revision_register >> 4) & 0xF; - lp->ChipRev = revision_register & 0xF; - - spin_lock_init(&lp->lock); - - return 0; - -err_out: - release_region (ioaddr, SMC_IO_EXTENT); - return retval; -} - -#if SMC_DEBUG > 2 -static void print_packet( byte * buf, int length ) -{ -#if 1 - int i; - int remainder; - int lines; - - printk("Packet of length %d \n", length ); - -#if SMC_DEBUG > 3 - lines = length / 16; - remainder = length % 16; - - for ( i = 0; i < lines ; i ++ ) { - int cur; - - for ( cur = 0; cur < 8; cur ++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printk("%02x%02x ", a, b ); - } - printk("\n"); - } - for ( i = 0; i < remainder/2 ; i++ ) { - byte a, b; - - a = *(buf ++ ); - b = *(buf ++ ); - printk("%02x%02x ", a, b ); - } - printk("\n"); -#endif -#endif -} -#endif - - -/* - * Open and Initialize the board - * - * Set up everything, reset the card, etc .. - * - */ -static int smc_open(struct net_device *dev) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - int ioaddr = dev->base_addr; - int i; /* used to set hw ethernet address */ - - PRINTK2("%s:smc_open\n", dev->name); - -#if 0 - /* clear out all the junk that was put here before... */ - memset(dev->priv, 0, sizeof(struct smc_local)); -#endif - - netif_start_queue(dev); -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - - // Setup the default Register Modes - lp->tcr_cur_mode = TCR_DEFAULT; - lp->rcr_cur_mode = RCR_DEFAULT; - lp->rpc_cur_mode = RPC_DEFAULT; - - // Set default parameters (files) - lp->ctl_swfdup = 0; - lp->ctl_ephloop = 0; - lp->ctl_miiop = 0; - lp->ctl_autoneg = 1; - lp->ctl_rfduplx = 1; - lp->ctl_rspeed = 100; - lp->ctl_afduplx = 1; - lp->ctl_aspeed = 100; - lp->ctl_lnkfail = 1; - lp->ctl_forcol = 0; - lp->ctl_filtcar = 0; - - /* reset the hardware */ - - smc_reset( dev ); - smc_enable( dev ); - - /* Configure the PHY */ - smc_phy_configure(dev); - - /* - According to Becker, I have to set the hardware address - at this point, because the (l)user can set it with an - ioctl. Easily done... - */ - SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) { - word address; - - address = dev->dev_addr[ i + 1 ] << 8 ; - address |= dev->dev_addr[ i ]; - outw( address, ioaddr + ADDR0_REG + i ); - } - -#ifdef CONFIG_SYSCTL - smc_sysctl_register(dev); -#endif /* CONFIG_SYSCTL */ - - netif_start_queue(dev); - return 0; -} - -/*-------------------------------------------------------- - . Called by the kernel to send a packet out into the void - . of the net. This routine is largely based on - . skeleton.c, from Becker. - .-------------------------------------------------------- -*/ -static void smc_timeout (struct net_device *dev) -{ - - struct smc_local *lp = (struct smc_local *)dev->priv; - unsigned long flags; - - /* - * Best would be to use synchronize_irq(); spin_lock() here - * lets make it work first.. - */ - - spin_lock_irqsave(&lp->lock, flags); - - PRINTK3("%s:smc_send_packet\n", dev->name); - - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - printk(KERN_WARNING "%s: transmit timed out, %s?\n",dev->name, tx_done(dev) ? "IRQ conflict" :"network cable problem"); - /* "kick" the adaptor */ - smc_reset( dev ); - smc_enable( dev ); - - /* Reconfigure the PHY */ - smc_phy_configure(dev); - - dev->trans_start = jiffies; - /* clear anything saved */ - ((struct smc_local *)dev->priv)->saved_skb = NULL; - - spin_unlock_irqrestore(&lp->lock, flags); - - netif_wake_queue(dev); -} - -/*-------------------------------------------------------------------- - . - . This is the main routine of the driver, to handle the net_device when - . it needs some attention. - . - . So: - . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge - . each to the interrupt register - . and finally restore state. - . - ---------------------------------------------------------------------*/ -static irqreturn_t smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - - byte status; - word card_stats; - byte mask; - int timeout; - /* state registers */ - word saved_bank; - word saved_pointer; - int handled = 0; - - PRINTK3("%s: SMC interrupt started \n", dev->name); - - if (dev == NULL) { - printk(KERN_WARNING "%s: irq %d for unknown device.\n", - dev->name, irq); - return IRQ_RETVAL(handled); - } - -/* will Linux let this happen ?? If not, this costs some speed - if ( dev->interrupt ) { - printk(KERN_WARNING "%s: interrupt inside interrupt.\n", - dev->name); - return; - } - - dev->interrupt = 1; */ - - spin_lock(&lp->lock); - - saved_bank = inw( ioaddr + BANK_SELECT ); - - SMC_SELECT_BANK(2); - saved_pointer = inw( ioaddr + PTR_REG ); - - /* read the interrupt status register */ - mask = inb( ioaddr + IM_REG ); - - /* disable all interrupts */ - outb( 0, ioaddr + IM_REG ); - - - /* set a timeout value, so I don't stay here forever */ - timeout = 8; - - PRINTK2(KERN_WARNING "%s: MASK IS %x \n", dev->name, mask); - do { - /* read the status flag, and mask it */ - status = inb( ioaddr + INT_REG ) & mask; - if (!status ) - break; - - handled = 1; - - PRINTK3(KERN_WARNING "%s: Handling interrupt status %x \n", - dev->name, status); - - if (status & IM_RCV_INT) { - /* Got a packet(s). */ - PRINTK2(KERN_WARNING - "%s: Receive Interrupt\n", dev->name); - smc_rcv(dev); - } else if (status & IM_TX_INT ) { - PRINTK2(KERN_WARNING "%s: TX ERROR handled\n", - dev->name); - smc_tx(dev); - // Acknowledge the interrupt - outb(IM_TX_INT, ioaddr + INT_REG ); -#if THROTTLE_TX_PKTS - netif_wake_queue(dev); -#endif - } else if (status & IM_TX_EMPTY_INT ) { - /* update stats */ - SMC_SELECT_BANK( 0 ); - card_stats = inw( ioaddr + COUNTER_REG ); - /* single collisions */ - lp->stats.collisions += card_stats & 0xF; - card_stats >>= 4; - /* multiple collisions */ - lp->stats.collisions += card_stats & 0xF; - - /* these are for when linux supports these statistics */ -#if 0 - card_stats >>= 4; - /* deferred */ - card_stats >>= 4; - /* excess deferred */ -#endif - SMC_SELECT_BANK( 2 ); - PRINTK2(KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n", - dev->name); - // Acknowledge the interrupt - outb( IM_TX_EMPTY_INT, ioaddr + INT_REG ); - mask &= ~IM_TX_EMPTY_INT; - lp->stats.tx_packets += lp->packets_waiting; - lp->packets_waiting = 0; - - } else if (status & IM_ALLOC_INT ) { - PRINTK2(KERN_DEBUG "%s: Allocation interrupt \n", - dev->name); - /* clear this interrupt so it doesn't happen again */ - mask &= ~IM_ALLOC_INT; - - smc_hardware_send_packet( dev ); - - /* enable xmit interrupts based on this */ - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); - - /* and let the card send more packets to me */ -#if ! THROTTLE_TX_PKTS - netif_wake_queue(dev); -#endif - - PRINTK2("%s: Handoff done successfully.\n", - dev->name); - } else if (status & IM_RX_OVRN_INT ) { - PRINTK2("%s: IM_RX_OVRN_INT \n",dev->name); - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - // Acknowledge the interrupt - outb( IM_RX_OVRN_INT, ioaddr + INT_REG ); - } else if (status & IM_EPH_INT ) { - PRINTK("%s: UNSUPPORTED: EPH INTERRUPT \n", - dev->name); - } else if (status & IM_MDINT ) { - smc_phy_interrupt(dev); - // Acknowledge the interrupt - outb(IM_MDINT, ioaddr + INT_REG ); - } else if (status & IM_ERCV_INT ) { - PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", - dev->name); - // Acknowledge the interrupt - outb( IM_ERCV_INT, ioaddr + INT_REG ); - } - } while ( timeout -- ); - - - /* restore register states */ - - SMC_SELECT_BANK( 2 ); - - outb( mask, ioaddr + IM_REG ); - - PRINTK3( KERN_WARNING "%s: MASK is now %x \n", dev->name, mask); - outw( saved_pointer, ioaddr + PTR_REG ); - - SMC_SELECT_BANK( saved_bank ); - - //dev->interrupt = 0; - PRINTK3("%s: Interrupt done\n", dev->name); - - spin_unlock(&lp->lock); - - return IRQ_RETVAL(handled); -} - -/*------------------------------------------------------------- - . - . smc_rcv - receive a packet from the card - . - . There is ( at least ) a packet waiting to be read from - . chip-memory. - . - . o Read the status - . o If an error, record it - . o otherwise, read in the packet - -------------------------------------------------------------- -*/ -static inline void smc_rcv(struct net_device *dev) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - int ioaddr = dev->base_addr; - int packet_number; - word status; - word packet_length; - - PRINTK3("%s:smc_rcv\n", dev->name); - - /* assume bank 2 */ - - packet_number = inw( ioaddr + RXFIFO_REG ); - - if ( packet_number & RXFIFO_REMPTY ) { - - /* we got called , but nothing was on the FIFO */ - PRINTK("%s: WARNING: smc_rcv with nothing on FIFO. \n", - dev->name); - /* don't need to restore anything */ - return; - } - - /* start reading from the start of the packet */ - outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + PTR_REG ); - - /* First two words are status and packet_length */ - status = inw( ioaddr + DATA_REG ); - packet_length = inw( ioaddr + DATA_REG ); - - packet_length &= 0x07ff; /* mask off top bits */ - - PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length ); - - if ( !(status & RS_ERRORS ) ){ - /* do stuff to make a new packet */ - struct sk_buff * skb; - byte * data; - - /* set multicast stats */ - if ( status & RS_MULTICAST ) - lp->stats.multicast++; - - // Allocate enough memory for entire receive frame, to be safe - skb = dev_alloc_skb( packet_length ); - - /* Adjust for having already read the first two words */ - packet_length -= 4; - - if ( skb == NULL ) { - printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", - dev->name); - lp->stats.rx_dropped++; - goto done; - } - - /* - ! This should work without alignment, but it could be - ! in the worse case - */ - /* TODO: Should I use 32bit alignment here ? */ - skb_reserve( skb, 2 ); /* 16 bit alignment */ - - skb->dev = dev; - - /* => - ODD-BYTE ISSUE : The odd byte problem has been fixed in the LAN91C111 Rev B. - So we check if the Chip Revision, stored in smsc_local->ChipRev, is = 1. - If so then we increment the packet length only if RS_ODDFRAME is set. - If the Chip's revision is equal to 0, then we blindly increment the packet length - by 1, thus always assuming that the packet is odd length, leaving the higher layer - to decide the actual length. - -- Pramod - <= */ - if ((9 == lp->ChipID) && (1 == lp->ChipRev)) - { - if (status & RS_ODDFRAME) - data = skb_put( skb, packet_length + 1 ); - else - data = skb_put( skb, packet_length); - } - else - { - // set odd length for bug in LAN91C111, REV A - // which never sets RS_ODDFRAME - data = skb_put( skb, packet_length + 1 ); - } - -#ifdef USE_32_BIT - PRINTK3(" Reading %d dwords (and %d bytes) \n", - packet_length >> 2, packet_length & 3 ); - /* QUESTION: Like in the TX routine, do I want - to send the DWORDs or the bytes first, or some - mixture. A mixture might improve already slow PIO - performance */ - insl(ioaddr + DATA_REG , data, packet_length >> 2 ); - /* read the left over bytes */ - insb( ioaddr + DATA_REG, data + (packet_length & 0xFFFFFC), - packet_length & 0x3 ); -#else - PRINTK3(" Reading %d words and %d byte(s) \n", - (packet_length >> 1 ), packet_length & 1 ); - insw(ioaddr + DATA_REG , data, packet_length >> 1); - -#endif // USE_32_BIT - -#if SMC_DEBUG > 2 - printk("Receiving Packet\n"); - print_packet( data, packet_length ); -#endif - - skb->protocol = eth_type_trans(skb, dev ); - netif_rx(skb); - lp->stats.rx_packets++; -#if defined(__m32r__) - lp->stats.rx_bytes += packet_length; -#endif - } else { - /* error ... */ - lp->stats.rx_errors++; - - if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++; - if ( status & (RS_TOOSHORT | RS_TOOLONG ) ) - lp->stats.rx_length_errors++; - if ( status & RS_BADCRC) lp->stats.rx_crc_errors++; - } - - while ( inw( ioaddr + MMU_CMD_REG ) & MC_BUSY ) - udelay(1); // Wait until not busy -done: - /* error or good, tell the card to get rid of this packet */ - outw( MC_RELEASE, ioaddr + MMU_CMD_REG ); - - return; -} - - -/************************************************************************* - . smc_tx - . - . Purpose: Handle a transmit error message. This will only be called - . when an error, because of the AUTO_RELEASE mode. - . - . Algorithm: - . Save pointer and packet no - . Get the packet no from the top of the queue - . check if it's valid ( if not, is this an error??? ) - . read the status word - . record the error - . ( resend? Not really, since we don't want old packets around ) - . Restore saved values - ************************************************************************/ -static inline void smc_tx( struct net_device * dev ) -{ - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - byte saved_packet; - byte packet_no; - word tx_status; - - - PRINTK3("%s:smc_tx\n", dev->name); - - /* assume bank 2 */ - - saved_packet = inb( ioaddr + PN_REG ); - packet_no = inw( ioaddr + RXFIFO_REG ); -#if defined(__m32r__) - /* If the TX FIFO is empty then nothing to do */ - if ( packet_no & TXFIFO_TEMPTY ) - return; - - packet_no &= 0x7F; -#else - packet_no &= 0x7F; - - /* If the TX FIFO is empty then nothing to do */ - if ( packet_no & TXFIFO_TEMPTY ) - return; -#endif - - /* select this as the packet to read from */ - outb( packet_no, ioaddr + PN_REG ); - - /* read the first word (status word) from this packet */ - outw( PTR_AUTOINC | PTR_READ, ioaddr + PTR_REG ); - - tx_status = inw( ioaddr + DATA_REG ); - PRINTK3("%s: TX DONE STATUS: %4x \n", dev->name, tx_status); - - lp->stats.tx_errors++; - if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++; - if ( tx_status & TS_LATCOL ) { - printk(KERN_DEBUG - "%s: Late collision occurred on last xmit.\n", - dev->name); - lp->stats.tx_window_errors++; - lp->ctl_forcol = 0; // Reset forced collsion - } -#if 0 - if ( tx_status & TS_16COL ) { ... } -#endif - - if ( tx_status & TS_SUCCESS ) { - // printk("%s: Successful packet caused interrupt \n", dev->name); - } - /* re-enable transmit */ - SMC_SELECT_BANK( 0 ); - outw( inw( ioaddr + TCR_REG ) | TCR_ENABLE, ioaddr + TCR_REG ); - - /* kill the packet */ - SMC_SELECT_BANK( 2 ); - outw( MC_FREEPKT, ioaddr + MMU_CMD_REG ); - - /* one less packet waiting for me */ - lp->packets_waiting--; - - /* Don't change Packet Number Reg until busy bit is cleared */ - /* Per LAN91C111 Spec, Page 50 */ - while ( inw( ioaddr + MMU_CMD_REG ) & MC_BUSY ); - - outb( saved_packet, ioaddr + PN_REG ); - return; -} - - -/*---------------------------------------------------- - . smc_close - . - . this makes the board clean up everything that it can - . and not talk to the outside world. Caused by - . an 'ifconfig ethX down' - . - -----------------------------------------------------*/ -static int smc_close(struct net_device *dev) -{ - netif_stop_queue(dev); - //dev->start = 0; - - PRINTK2("%s:smc_close\n", dev->name); - -#ifdef CONFIG_SYSCTL - smc_sysctl_unregister(dev); -#endif /* CONFIG_SYSCTL */ - - /* clear everything */ - smc_shutdown( dev->base_addr ); - - /* Update the statistics here. */ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - - return 0; -} - -/*------------------------------------------------------------ - . Get the current statistics. - . This may be called with the card open or closed. - .-------------------------------------------------------------*/ -static struct net_device_stats* smc_query_statistics(struct net_device *dev) { - struct smc_local *lp = (struct smc_local *)dev->priv; - - PRINTK2("%s:smc_query_statistics\n", dev->name); - - return &lp->stats; -} - -/*----------------------------------------------------------- - . smc_set_multicast_list - . - . This routine will, depending on the values passed to it, - . either make it accept multicast packets, go into - . promiscuous mode ( for TCPDUMP and cousins ) or accept - . a select set of multicast packets -*/ -static void smc_set_multicast_list(struct net_device *dev) -{ - short ioaddr = dev->base_addr; - - PRINTK2("%s:smc_set_multicast_list\n", dev->name); - - SMC_SELECT_BANK(0); - if ( dev->flags & IFF_PROMISC ) - { - PRINTK2("%s:smc_set_multicast_list:RCR_PRMS\n", dev->name); - outw( inw(ioaddr + RCR_REG ) | RCR_PRMS, ioaddr + RCR_REG ); - } - -/* BUG? I never disable promiscuous mode if multicasting was turned on. - Now, I turn off promiscuous mode, but I don't do anything to multicasting - when promiscuous mode is turned on. -*/ - - /* Here, I am setting this to accept all multicast packets. - I don't need to zero the multicast table, because the flag is - checked before the table is - */ - else if (dev->flags & IFF_ALLMULTI) - { - outw( inw(ioaddr + RCR_REG ) | RCR_ALMUL, ioaddr + RCR_REG ); - PRINTK2("%s:smc_set_multicast_list:RCR_ALMUL\n", dev->name); - } - - /* We just get all multicast packets even if we only want them - . from one source. This will be changed at some future - . point. */ - else if (dev->mc_count ) { - /* support hardware multicasting */ - - /* be sure I get rid of flags I might have set */ - outw( inw( ioaddr + RCR_REG ) & ~(RCR_PRMS | RCR_ALMUL), - ioaddr + RCR_REG ); - /* NOTE: this has to set the bank, so make sure it is the - last thing called. The bank is set to zero at the top */ - smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); - } else { - PRINTK2("%s:smc_set_multicast_list:~(RCR_PRMS|RCR_ALMUL)\n", - dev->name); - outw( inw( ioaddr + RCR_REG ) & ~(RCR_PRMS | RCR_ALMUL), - ioaddr + RCR_REG ); - - /* - since I'm disabling all multicast entirely, I need to - clear the multicast list - */ - SMC_SELECT_BANK( 3 ); - outw( 0, ioaddr + MCAST_REG1 ); - outw( 0, ioaddr + MCAST_REG2 ); - outw( 0, ioaddr + MCAST_REG3 ); - outw( 0, ioaddr + MCAST_REG4 ); - } -} - -#ifdef MODULE - -static struct net_device *devSMC91111; -int nowait = 0; - -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(nowait, "i"); - -/*------------------------------------------------------------ - . Module initialization function - .-------------------------------------------------------------*/ -int init_module(void) -{ - PRINTK2("CARDNAME:init_module\n"); - if (io == 0) - printk(KERN_WARNING - CARDNAME": You shouldn't use auto-probing with insmod!\n" ); - - /* copy the parameters from insmod into the device structure */ - devSMC91111 = smc_init(-1); - if (IS_ERR(devSMC91111)) - return PTR_ERR(devSMC91111); - - return 0; -} - -/*------------------------------------------------------------ - . Cleanup when module is removed with rmmod - .-------------------------------------------------------------*/ -void cleanup_module(void) -{ - unregister_netdev(devSMC91111); - free_irq(devSMC91111->irq, devSMC91111); - release_region(devSMC91111->base_addr, SMC_IO_EXTENT); - free_netdev(devSMC91111); -} - -#endif /* MODULE */ - - -#ifdef CONFIG_SYSCTL - - -/*------------------------------------------------------------ - . Modify a bit in the LAN91C111 register set - .-------------------------------------------------------------*/ -static word smc_modify_regbit(int bank, int ioaddr, int reg, - unsigned int bit, int val) -{ - word regval; - - SMC_SELECT_BANK( bank ); - - regval = inw( ioaddr+reg ); - if (val) - regval |= bit; - else - regval &= ~bit; - - outw( regval, ioaddr ); - return(regval); -} - - -/*------------------------------------------------------------ - . Retrieve a bit in the LAN91C111 register set - .-------------------------------------------------------------*/ -static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit) -{ - SMC_SELECT_BANK( bank ); - if ( inw( ioaddr+reg ) & bit) - return(1); - else - return(0); -} - - -/*------------------------------------------------------------ - . Modify a LAN91C111 register (word access only) - .-------------------------------------------------------------*/ -static void smc_modify_reg(int bank, int ioaddr, int reg, word val) -{ - SMC_SELECT_BANK( bank ); - outw( val, ioaddr+reg ); -} - - -/*------------------------------------------------------------ - . Retrieve a LAN91C111 register (word access only) - .-------------------------------------------------------------*/ -static int smc_get_reg(int bank, int ioaddr, int reg) -{ - SMC_SELECT_BANK( bank ); - return(inw( ioaddr+reg )); -} - - -static const char smc_info_string[] = -"\n" -"info Provides this information blurb\n" -"swver Prints the software version information of this driver\n" -"autoneg Auto-negotiate Mode = 1\n" -"rspeed Requested Speed, 100=100Mbps, 10=10Mpbs\n" -"rfduplx Requested Full Duplex Operation\n" -"aspeed Actual Speed, 100=100Mbps, 10=10Mpbs\n" -"afduplx Actual Full Duplex Operation\n" -"lnkfail PHY Link Failure when 1\n" -"miiop External MII when 1, Internal PHY when 0\n" -"swfdup Switched Full Duplex Mode (allowed only in MII operation)\n" -"ephloop EPH Block Loopback\n" -"forcol Force a collision\n" -"filtcar Filter leading edge of carrier sense for 12 bit times\n" -"freemem Free buffer memory in bytes\n" -"totmem Total buffer memory in bytes\n" -"leda Output of LED-A (green)\n" -"ledb Output of LED-B (yellow)\n" -"chiprev Revision ID of the LAN91C111 chip\n" -""; - -/*------------------------------------------------------------ - . Sysctl handler for all integer parameters - .-------------------------------------------------------------*/ -static int smc_sysctl_handler(ctl_table *ctl, int write, struct file * filp, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct net_device *dev = (struct net_device*)ctl->extra1; - struct smc_local *lp = (struct smc_local *)ctl->extra2; - int ioaddr = dev->base_addr; - int *valp = ctl->data; - int val; - int ret; - - // Update parameters from the real registers - switch (ctl->ctl_name) - { - case CTL_SMC_FORCOL: - *valp = smc_get_regbit(0, ioaddr, TCR_REG, TCR_FORCOL); - break; - - case CTL_SMC_FREEMEM: - *valp = ( (word)smc_get_reg(0, ioaddr, MIR_REG) >> 8 ) - * LAN91C111_MEMORY_MULTIPLIER; - break; - - - case CTL_SMC_TOTMEM: - *valp = ( smc_get_reg(0, ioaddr, MIR_REG) & (word)0x00ff ) - * LAN91C111_MEMORY_MULTIPLIER; - break; - - case CTL_SMC_CHIPREV: - *valp = smc_get_reg(3, ioaddr, REV_REG); - break; - - case CTL_SMC_AFDUPLX: - *valp = (lp->lastPhy18 & PHY_INT_DPLXDET) ? 1 : 0; - break; - - case CTL_SMC_ASPEED: - *valp = (lp->lastPhy18 & PHY_INT_SPDDET) ? 100 : 10; - break; - - case CTL_SMC_LNKFAIL: - *valp = (lp->lastPhy18 & PHY_INT_LNKFAIL) ? 1 : 0; - break; - - case CTL_SMC_LEDA: - *valp = (lp->rpc_cur_mode >> RPC_LSXA_SHFT) & (word)0x0007; - break; - - case CTL_SMC_LEDB: - *valp = (lp->rpc_cur_mode >> RPC_LSXB_SHFT) & (word)0x0007; - break; - - case CTL_SMC_MIIOP: - *valp = smc_get_regbit(1, ioaddr, CONFIG_REG, CONFIG_EXT_PHY); - break; - -#ifdef SMC_DEBUG - case CTL_SMC_REG_BSR: // Bank Select - *valp = smc_get_reg(0, ioaddr, BSR_REG); - break; - - case CTL_SMC_REG_TCR: // Transmit Control - *valp = smc_get_reg(0, ioaddr, TCR_REG); - break; - - case CTL_SMC_REG_ESR: // EPH Status - *valp = smc_get_reg(0, ioaddr, EPH_STATUS_REG); - break; - - case CTL_SMC_REG_RCR: // Receive Control - *valp = smc_get_reg(0, ioaddr, RCR_REG); - break; - - case CTL_SMC_REG_CTRR: // Counter - *valp = smc_get_reg(0, ioaddr, COUNTER_REG); - break; - - case CTL_SMC_REG_MIR: // Memory Information - *valp = smc_get_reg(0, ioaddr, MIR_REG); - break; - - case CTL_SMC_REG_RPCR: // Receive/Phy Control - *valp = smc_get_reg(0, ioaddr, RPC_REG); - break; - - case CTL_SMC_REG_CFGR: // Configuration - *valp = smc_get_reg(1, ioaddr, CONFIG_REG); - break; - - case CTL_SMC_REG_BAR: // Base Address - *valp = smc_get_reg(1, ioaddr, BASE_REG); - break; - - case CTL_SMC_REG_IAR0: // Individual Address - *valp = smc_get_reg(1, ioaddr, ADDR0_REG); - break; - - case CTL_SMC_REG_IAR1: // Individual Address - *valp = smc_get_reg(1, ioaddr, ADDR1_REG); - break; - - case CTL_SMC_REG_IAR2: // Individual Address - *valp = smc_get_reg(1, ioaddr, ADDR2_REG); - break; - - case CTL_SMC_REG_GPR: // General Purpose - *valp = smc_get_reg(1, ioaddr, GP_REG); - break; - - case CTL_SMC_REG_CTLR: // Control - *valp = smc_get_reg(1, ioaddr, CTL_REG); - break; - - case CTL_SMC_REG_MCR: // MMU Command - *valp = smc_get_reg(2, ioaddr, MMU_CMD_REG); - break; - - case CTL_SMC_REG_PNR: // Packet Number - *valp = smc_get_reg(2, ioaddr, PN_REG); - break; - - case CTL_SMC_REG_FPR: // Allocation Result/FIFO Ports - *valp = smc_get_reg(2, ioaddr, RXFIFO_REG); - break; - - case CTL_SMC_REG_PTR: // Pointer - *valp = smc_get_reg(2, ioaddr, PTR_REG); - break; - - case CTL_SMC_REG_DR: // Data - *valp = smc_get_reg(2, ioaddr, DATA_REG); - break; - - case CTL_SMC_REG_ISR: // Interrupt Status/Mask - *valp = smc_get_reg(2, ioaddr, INT_REG); - break; - - case CTL_SMC_REG_MTR1: // Multicast Table Entry 1 - *valp = smc_get_reg(3, ioaddr, MCAST_REG1); - break; - - case CTL_SMC_REG_MTR2: // Multicast Table Entry 2 - *valp = smc_get_reg(3, ioaddr, MCAST_REG2); - break; - - case CTL_SMC_REG_MTR3: // Multicast Table Entry 3 - *valp = smc_get_reg(3, ioaddr, MCAST_REG3); - break; - - case CTL_SMC_REG_MTR4: // Multicast Table Entry 4 - *valp = smc_get_reg(3, ioaddr, MCAST_REG4); - break; - - case CTL_SMC_REG_MIIR: // Management Interface - *valp = smc_get_reg(3, ioaddr, MII_REG); - break; - - case CTL_SMC_REG_REVR: // Revision - *valp = smc_get_reg(3, ioaddr, REV_REG); - break; - - case CTL_SMC_REG_ERCVR: // Early RCV - *valp = smc_get_reg(3, ioaddr, ERCV_REG); - break; - - case CTL_SMC_REG_EXTR: // External - *valp = smc_get_reg(7, ioaddr, EXT_REG); - break; - - case CTL_SMC_PHY_CTRL: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_CNTL_REG); - break; - - case CTL_SMC_PHY_STAT: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_STAT_REG); - break; - - case CTL_SMC_PHY_ID1: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_ID1_REG); - break; - - case CTL_SMC_PHY_ID2: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_ID2_REG); - break; - - case CTL_SMC_PHY_ADC: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_AD_REG); - break; - - case CTL_SMC_PHY_REMC: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_RMT_REG); - break; - - case CTL_SMC_PHY_CFG1: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_CFG1_REG); - break; - - case CTL_SMC_PHY_CFG2: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_CFG2_REG); - break; - - case CTL_SMC_PHY_INT: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_INT_REG); - break; - - case CTL_SMC_PHY_MASK: - *valp = smc_read_phy_register(ioaddr, lp->phyaddr, - PHY_MASK_REG); - break; - -#endif // SMC_DEBUG - - default: - // Just ignore unsupported parameters - break; - } - - // Save old state - val = *valp; - - // Perform the generic integer operation - if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos)) != 0) - return(ret); - - // Write changes out to the registers - if (write && *valp != val) { - - val = *valp; - switch (ctl->ctl_name) { - - case CTL_SMC_SWFDUP: - if (val) - lp->tcr_cur_mode |= TCR_SWFDUP; - else - lp->tcr_cur_mode &= ~TCR_SWFDUP; - - smc_modify_regbit(0, ioaddr, TCR_REG, TCR_SWFDUP, val); - break; - - case CTL_SMC_EPHLOOP: - if (val) - lp->tcr_cur_mode |= TCR_EPH_LOOP; - else - lp->tcr_cur_mode &= ~TCR_EPH_LOOP; - - smc_modify_regbit(0, ioaddr, TCR_REG, TCR_EPH_LOOP, val); - break; - - case CTL_SMC_FORCOL: - if (val) - lp->tcr_cur_mode |= TCR_FORCOL; - else - lp->tcr_cur_mode &= ~TCR_FORCOL; - - // Update the EPH block - smc_modify_regbit(0, ioaddr, TCR_REG, TCR_FORCOL, val); - break; - - case CTL_SMC_FILTCAR: - if (val) - lp->rcr_cur_mode |= RCR_FILT_CAR; - else - lp->rcr_cur_mode &= ~RCR_FILT_CAR; - - // Update the EPH block - smc_modify_regbit(0, ioaddr, RCR_REG, RCR_FILT_CAR, val); - break; - - case CTL_SMC_RFDUPLX: - // Disallow changes if in auto-negotiation mode - if (lp->ctl_autoneg) - break; - - if (val) - { - lp->rpc_cur_mode |= RPC_DPLX; - } - else - { - lp->rpc_cur_mode &= ~RPC_DPLX; - } - - // Reconfigure the PHY - smc_phy_configure(dev); - - break; - - case CTL_SMC_RSPEED: - // Disallow changes if in auto-negotiation mode - if (lp->ctl_autoneg) - break; - - if (val > 10) - lp->rpc_cur_mode |= RPC_SPEED; - else - lp->rpc_cur_mode &= ~RPC_SPEED; - - // Reconfigure the PHY - smc_phy_configure(dev); - - break; - - case CTL_SMC_AUTONEG: - if (val) - lp->rpc_cur_mode |= RPC_ANEG; - else - lp->rpc_cur_mode &= ~RPC_ANEG; - - // Reconfigure the PHY - smc_phy_configure(dev); - - break; - - case CTL_SMC_LEDA: - val &= 0x07; // Restrict to 3 ls bits - lp->rpc_cur_mode &= ~(word)(0x07<rpc_cur_mode |= (word)(val<rpc_cur_mode); - break; - - case CTL_SMC_LEDB: - val &= 0x07; // Restrict to 3 ls bits - lp->rpc_cur_mode &= ~(word)(0x07<rpc_cur_mode |= (word)(val<rpc_cur_mode); - break; - - case CTL_SMC_MIIOP: - // Update the Internal PHY block - smc_modify_regbit(1, ioaddr, CONFIG_REG, - CONFIG_EXT_PHY, val); - break; - -#ifdef SMC_DEBUG - case CTL_SMC_REG_BSR: // Bank Select - smc_modify_reg(0, ioaddr, BSR_REG, val); - break; - - case CTL_SMC_REG_TCR: // Transmit Control - smc_modify_reg(0, ioaddr, TCR_REG, val); - break; - - case CTL_SMC_REG_ESR: // EPH Status - smc_modify_reg(0, ioaddr, EPH_STATUS_REG, val); - break; - - case CTL_SMC_REG_RCR: // Receive Control - smc_modify_reg(0, ioaddr, RCR_REG, val); - break; - - case CTL_SMC_REG_CTRR: // Counter - smc_modify_reg(0, ioaddr, COUNTER_REG, val); - break; - - case CTL_SMC_REG_MIR: // Memory Information - smc_modify_reg(0, ioaddr, MIR_REG, val); - break; - - case CTL_SMC_REG_RPCR: // Receive/Phy Control - smc_modify_reg(0, ioaddr, RPC_REG, val); - break; - - case CTL_SMC_REG_CFGR: // Configuration - smc_modify_reg(1, ioaddr, CONFIG_REG, val); - break; - - case CTL_SMC_REG_BAR: // Base Address - smc_modify_reg(1, ioaddr, BASE_REG, val); - break; - - case CTL_SMC_REG_IAR0: // Individual Address - smc_modify_reg(1, ioaddr, ADDR0_REG, val); - break; - - case CTL_SMC_REG_IAR1: // Individual Address - smc_modify_reg(1, ioaddr, ADDR1_REG, val); - break; - - case CTL_SMC_REG_IAR2: // Individual Address - smc_modify_reg(1, ioaddr, ADDR2_REG, val); - break; - - case CTL_SMC_REG_GPR: // General Purpose - smc_modify_reg(1, ioaddr, GP_REG, val); - break; - - case CTL_SMC_REG_CTLR: // Control - smc_modify_reg(1, ioaddr, CTL_REG, val); - break; - - case CTL_SMC_REG_MCR: // MMU Command - smc_modify_reg(2, ioaddr, MMU_CMD_REG, val); - break; - - case CTL_SMC_REG_PNR: // Packet Number - smc_modify_reg(2, ioaddr, PN_REG, val); - break; - - case CTL_SMC_REG_FPR: // Allocation Result/FIFO Ports - smc_modify_reg(2, ioaddr, RXFIFO_REG, val); - break; - - case CTL_SMC_REG_PTR: // Pointer - smc_modify_reg(2, ioaddr, PTR_REG, val); - break; - - case CTL_SMC_REG_DR: // Data - smc_modify_reg(2, ioaddr, DATA_REG, val); - break; - - case CTL_SMC_REG_ISR: // Interrupt Status/Mask - smc_modify_reg(2, ioaddr, INT_REG, val); - break; - - case CTL_SMC_REG_MTR1: // Multicast Table Entry 1 - smc_modify_reg(3, ioaddr, MCAST_REG1, val); - break; - - case CTL_SMC_REG_MTR2: // Multicast Table Entry 2 - smc_modify_reg(3, ioaddr, MCAST_REG2, val); - break; - - case CTL_SMC_REG_MTR3: // Multicast Table Entry 3 - smc_modify_reg(3, ioaddr, MCAST_REG3, val); - break; - - case CTL_SMC_REG_MTR4: // Multicast Table Entry 4 - smc_modify_reg(3, ioaddr, MCAST_REG4, val); - break; - - case CTL_SMC_REG_MIIR: // Management Interface - smc_modify_reg(3, ioaddr, MII_REG, val); - break; - - case CTL_SMC_REG_REVR: // Revision - smc_modify_reg(3, ioaddr, REV_REG, val); - break; - - case CTL_SMC_REG_ERCVR: // Early RCV - smc_modify_reg(3, ioaddr, ERCV_REG, val); - break; - - case CTL_SMC_REG_EXTR: // External - smc_modify_reg(7, ioaddr, EXT_REG, val); - break; - - case CTL_SMC_PHY_CTRL: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_CNTL_REG, val); - break; - - case CTL_SMC_PHY_STAT: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_STAT_REG, val); - break; - - case CTL_SMC_PHY_ID1: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_ID1_REG, val); - break; - - case CTL_SMC_PHY_ID2: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_ID2_REG, val); - break; - - case CTL_SMC_PHY_ADC: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_AD_REG, val); - break; - - case CTL_SMC_PHY_REMC: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_RMT_REG, val); - break; - - case CTL_SMC_PHY_CFG1: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_CFG1_REG, val); - break; - - case CTL_SMC_PHY_CFG2: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_CFG2_REG, val); - break; - - case CTL_SMC_PHY_INT: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_INT_REG, val); - break; - - case CTL_SMC_PHY_MASK: - smc_write_phy_register(ioaddr, lp->phyaddr, - PHY_MASK_REG, val); - break; - -#endif // SMC_DEBUG - - default: - // Just ignore unsupported parameters - break; - } // end switch - - } // end if - - return ret; -} - -/*------------------------------------------------------------ - . Sysctl registration function for all parameters (files) - .-------------------------------------------------------------*/ -static void smc_sysctl_register(struct net_device *dev) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - static int ctl_name = CTL_SMC; - ctl_table* ct; - int i; - - // Make sure the ctl_tables start out as all zeros - memset(lp->root_table, 0, sizeof lp->root_table); - memset(lp->eth_table, 0, sizeof lp->eth_table); - memset(lp->param_table, 0, sizeof lp->param_table); - - // Initialize the root table - ct = lp->root_table; - ct->ctl_name = CTL_DEV; - ct->procname = "dev"; - ct->maxlen = 0; - ct->mode = 0555; - ct->child = lp->eth_table; - // remaining fields are zero - - // Initialize the ethX table (this device's table) - ct = lp->eth_table; - ct->ctl_name = ctl_name++; // Must be unique - ct->procname = dev->name; - ct->maxlen = 0; - ct->mode = 0555; - ct->child = lp->param_table; - // remaining fields are zero - - // Initialize the parameter (files) table - // Make sure the last entry remains null - ct = lp->param_table; - for (i = 0; i < (CTL_SMC_LAST_ENTRY-1); ++i) - { - // Initialize fields common to all table entries - ct[i].proc_handler = smc_sysctl_handler; - ct[i].extra1 = (void*)dev; // Save our device pointer - ct[i].extra2 = (void*)lp; // Save our smc_local data pointer - } - - // INFO - this is our only string parameter - i = 0; - ct[i].proc_handler = proc_dostring; // use default handler - ct[i].ctl_name = CTL_SMC_INFO; - ct[i].procname = "info"; - ct[i].data = (void*)smc_info_string; - ct[i].maxlen = sizeof smc_info_string; - ct[i].mode = 0444; // Read only - - // SWVER - ++i; - ct[i].proc_handler = proc_dostring; // use default handler - ct[i].ctl_name = CTL_SMC_SWVER; - ct[i].procname = "swver"; - ct[i].data = (void*)version; - ct[i].maxlen = sizeof version; - ct[i].mode = 0444; // Read only - - // SWFDUP - ++i; - ct[i].ctl_name = CTL_SMC_SWFDUP; - ct[i].procname = "swfdup"; - ct[i].data = (void*)&(lp->ctl_swfdup); - ct[i].maxlen = sizeof lp->ctl_swfdup; - ct[i].mode = 0644; // Read by all, write by root - - // EPHLOOP - ++i; - ct[i].ctl_name = CTL_SMC_EPHLOOP; - ct[i].procname = "ephloop"; - ct[i].data = (void*)&(lp->ctl_ephloop); - ct[i].maxlen = sizeof lp->ctl_ephloop; - ct[i].mode = 0644; // Read by all, write by root - - // MIIOP - ++i; - ct[i].ctl_name = CTL_SMC_MIIOP; - ct[i].procname = "miiop"; - ct[i].data = (void*)&(lp->ctl_miiop); - ct[i].maxlen = sizeof lp->ctl_miiop; - ct[i].mode = 0644; // Read by all, write by root - - // AUTONEG - ++i; - ct[i].ctl_name = CTL_SMC_AUTONEG; - ct[i].procname = "autoneg"; - ct[i].data = (void*)&(lp->ctl_autoneg); - ct[i].maxlen = sizeof lp->ctl_autoneg; - ct[i].mode = 0644; // Read by all, write by root - - // RFDUPLX - ++i; - ct[i].ctl_name = CTL_SMC_RFDUPLX; - ct[i].procname = "rfduplx"; - ct[i].data = (void*)&(lp->ctl_rfduplx); - ct[i].maxlen = sizeof lp->ctl_rfduplx; - ct[i].mode = 0644; // Read by all, write by root - - // RSPEED - ++i; - ct[i].ctl_name = CTL_SMC_RSPEED; - ct[i].procname = "rspeed"; - ct[i].data = (void*)&(lp->ctl_rspeed); - ct[i].maxlen = sizeof lp->ctl_rspeed; - ct[i].mode = 0644; // Read by all, write by root - - // AFDUPLX - ++i; - ct[i].ctl_name = CTL_SMC_AFDUPLX; - ct[i].procname = "afduplx"; - ct[i].data = (void*)&(lp->ctl_afduplx); - ct[i].maxlen = sizeof lp->ctl_afduplx; - ct[i].mode = 0444; // Read only - - // ASPEED - ++i; - ct[i].ctl_name = CTL_SMC_ASPEED; - ct[i].procname = "aspeed"; - ct[i].data = (void*)&(lp->ctl_aspeed); - ct[i].maxlen = sizeof lp->ctl_aspeed; - ct[i].mode = 0444; // Read only - - // LNKFAIL - ++i; - ct[i].ctl_name = CTL_SMC_LNKFAIL; - ct[i].procname = "lnkfail"; - ct[i].data = (void*)&(lp->ctl_lnkfail); - ct[i].maxlen = sizeof lp->ctl_lnkfail; - ct[i].mode = 0444; // Read only - - // FORCOL - ++i; - ct[i].ctl_name = CTL_SMC_FORCOL; - ct[i].procname = "forcol"; - ct[i].data = (void*)&(lp->ctl_forcol); - ct[i].maxlen = sizeof lp->ctl_forcol; - ct[i].mode = 0644; // Read by all, write by root - - // FILTCAR - ++i; - ct[i].ctl_name = CTL_SMC_FILTCAR; - ct[i].procname = "filtcar"; - ct[i].data = (void*)&(lp->ctl_filtcar); - ct[i].maxlen = sizeof lp->ctl_filtcar; - ct[i].mode = 0644; // Read by all, write by root - - // FREEMEM - ++i; - ct[i].ctl_name = CTL_SMC_FREEMEM; - ct[i].procname = "freemem"; - ct[i].data = (void*)&(lp->ctl_freemem); - ct[i].maxlen = sizeof lp->ctl_freemem; - ct[i].mode = 0444; // Read only - - // TOTMEM - ++i; - ct[i].ctl_name = CTL_SMC_TOTMEM; - ct[i].procname = "totmem"; - ct[i].data = (void*)&(lp->ctl_totmem); - ct[i].maxlen = sizeof lp->ctl_totmem; - ct[i].mode = 0444; // Read only - - // LEDA - ++i; - ct[i].ctl_name = CTL_SMC_LEDA; - ct[i].procname = "leda"; - ct[i].data = (void*)&(lp->ctl_leda); - ct[i].maxlen = sizeof lp->ctl_leda; - ct[i].mode = 0644; // Read by all, write by root - - // LEDB - ++i; - ct[i].ctl_name = CTL_SMC_LEDB; - ct[i].procname = "ledb"; - ct[i].data = (void*)&(lp->ctl_ledb); - ct[i].maxlen = sizeof lp->ctl_ledb; - ct[i].mode = 0644; // Read by all, write by root - - // CHIPREV - ++i; - ct[i].ctl_name = CTL_SMC_CHIPREV; - ct[i].procname = "chiprev"; - ct[i].data = (void*)&(lp->ctl_chiprev); - ct[i].maxlen = sizeof lp->ctl_chiprev; - ct[i].mode = 0444; // Read only - -#ifdef SMC_DEBUG - // REG_BSR - ++i; - ct[i].ctl_name = CTL_SMC_REG_BSR; - ct[i].procname = "reg_bsr"; - ct[i].data = (void*)&(lp->ctl_reg_bsr); - ct[i].maxlen = sizeof lp->ctl_reg_bsr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_TCR - ++i; - ct[i].ctl_name = CTL_SMC_REG_TCR; - ct[i].procname = "reg_tcr"; - ct[i].data = (void*)&(lp->ctl_reg_tcr); - ct[i].maxlen = sizeof lp->ctl_reg_tcr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_ESR - ++i; - ct[i].ctl_name = CTL_SMC_REG_ESR; - ct[i].procname = "reg_esr"; - ct[i].data = (void*)&(lp->ctl_reg_esr); - ct[i].maxlen = sizeof lp->ctl_reg_esr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_RCR - ++i; - ct[i].ctl_name = CTL_SMC_REG_RCR; - ct[i].procname = "reg_rcr"; - ct[i].data = (void*)&(lp->ctl_reg_rcr); - ct[i].maxlen = sizeof lp->ctl_reg_rcr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_CTRR - ++i; - ct[i].ctl_name = CTL_SMC_REG_CTRR; - ct[i].procname = "reg_ctrr"; - ct[i].data = (void*)&(lp->ctl_reg_ctrr); - ct[i].maxlen = sizeof lp->ctl_reg_ctrr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MIR - ++i; - ct[i].ctl_name = CTL_SMC_REG_MIR; - ct[i].procname = "reg_mir"; - ct[i].data = (void*)&(lp->ctl_reg_mir); - ct[i].maxlen = sizeof lp->ctl_reg_mir; - ct[i].mode = 0644; // Read by all, write by root - - // REG_RPCR - ++i; - ct[i].ctl_name = CTL_SMC_REG_RPCR; - ct[i].procname = "reg_rpcr"; - ct[i].data = (void*)&(lp->ctl_reg_rpcr); - ct[i].maxlen = sizeof lp->ctl_reg_rpcr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_CFGR - ++i; - ct[i].ctl_name = CTL_SMC_REG_CFGR; - ct[i].procname = "reg_cfgr"; - ct[i].data = (void*)&(lp->ctl_reg_cfgr); - ct[i].maxlen = sizeof lp->ctl_reg_cfgr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_BAR - ++i; - ct[i].ctl_name = CTL_SMC_REG_BAR; - ct[i].procname = "reg_bar"; - ct[i].data = (void*)&(lp->ctl_reg_bar); - ct[i].maxlen = sizeof lp->ctl_reg_bar; - ct[i].mode = 0644; // Read by all, write by root - - // REG_IAR0 - ++i; - ct[i].ctl_name = CTL_SMC_REG_IAR0; - ct[i].procname = "reg_iar0"; - ct[i].data = (void*)&(lp->ctl_reg_iar0); - ct[i].maxlen = sizeof lp->ctl_reg_iar0; - ct[i].mode = 0644; // Read by all, write by root - - // REG_IAR1 - ++i; - ct[i].ctl_name = CTL_SMC_REG_IAR1; - ct[i].procname = "reg_iar1"; - ct[i].data = (void*)&(lp->ctl_reg_iar1); - ct[i].maxlen = sizeof lp->ctl_reg_iar1; - ct[i].mode = 0644; // Read by all, write by root - - // REG_IAR2 - ++i; - ct[i].ctl_name = CTL_SMC_REG_IAR2; - ct[i].procname = "reg_iar2"; - ct[i].data = (void*)&(lp->ctl_reg_iar2); - ct[i].maxlen = sizeof lp->ctl_reg_iar2; - ct[i].mode = 0644; // Read by all, write by root - - // REG_GPR - ++i; - ct[i].ctl_name = CTL_SMC_REG_GPR; - ct[i].procname = "reg_gpr"; - ct[i].data = (void*)&(lp->ctl_reg_gpr); - ct[i].maxlen = sizeof lp->ctl_reg_gpr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_CTLR - ++i; - ct[i].ctl_name = CTL_SMC_REG_CTLR; - ct[i].procname = "reg_ctlr"; - ct[i].data = (void*)&(lp->ctl_reg_ctlr); - ct[i].maxlen = sizeof lp->ctl_reg_ctlr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MCR - ++i; - ct[i].ctl_name = CTL_SMC_REG_MCR; - ct[i].procname = "reg_mcr"; - ct[i].data = (void*)&(lp->ctl_reg_mcr); - ct[i].maxlen = sizeof lp->ctl_reg_mcr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_PNR - ++i; - ct[i].ctl_name = CTL_SMC_REG_PNR; - ct[i].procname = "reg_pnr"; - ct[i].data = (void*)&(lp->ctl_reg_pnr); - ct[i].maxlen = sizeof lp->ctl_reg_pnr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_FPR - ++i; - ct[i].ctl_name = CTL_SMC_REG_FPR; - ct[i].procname = "reg_fpr"; - ct[i].data = (void*)&(lp->ctl_reg_fpr); - ct[i].maxlen = sizeof lp->ctl_reg_fpr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_PTR - ++i; - ct[i].ctl_name = CTL_SMC_REG_PTR; - ct[i].procname = "reg_ptr"; - ct[i].data = (void*)&(lp->ctl_reg_ptr); - ct[i].maxlen = sizeof lp->ctl_reg_ptr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_DR - ++i; - ct[i].ctl_name = CTL_SMC_REG_DR; - ct[i].procname = "reg_dr"; - ct[i].data = (void*)&(lp->ctl_reg_dr); - ct[i].maxlen = sizeof lp->ctl_reg_dr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_ISR - ++i; - ct[i].ctl_name = CTL_SMC_REG_ISR; - ct[i].procname = "reg_isr"; - ct[i].data = (void*)&(lp->ctl_reg_isr); - ct[i].maxlen = sizeof lp->ctl_reg_isr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MTR1 - ++i; - ct[i].ctl_name = CTL_SMC_REG_MTR1; - ct[i].procname = "reg_mtr1"; - ct[i].data = (void*)&(lp->ctl_reg_mtr1); - ct[i].maxlen = sizeof lp->ctl_reg_mtr1; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MTR2 - ++i; - ct[i].ctl_name = CTL_SMC_REG_MTR2; - ct[i].procname = "reg_mtr2"; - ct[i].data = (void*)&(lp->ctl_reg_mtr2); - ct[i].maxlen = sizeof lp->ctl_reg_mtr2; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MTR3 - ++i; - ct[i].ctl_name = CTL_SMC_REG_MTR3; - ct[i].procname = "reg_mtr3"; - ct[i].data = (void*)&(lp->ctl_reg_mtr3); - ct[i].maxlen = sizeof lp->ctl_reg_mtr3; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MTR4 - ++i; - ct[i].ctl_name = CTL_SMC_REG_MTR4; - ct[i].procname = "reg_mtr4"; - ct[i].data = (void*)&(lp->ctl_reg_mtr4); - ct[i].maxlen = sizeof lp->ctl_reg_mtr4; - ct[i].mode = 0644; // Read by all, write by root - - // REG_MIIR - ++i; - ct[i].ctl_name = CTL_SMC_REG_MIIR; - ct[i].procname = "reg_miir"; - ct[i].data = (void*)&(lp->ctl_reg_miir); - ct[i].maxlen = sizeof lp->ctl_reg_miir; - ct[i].mode = 0644; // Read by all, write by root - - // REG_REVR - ++i; - ct[i].ctl_name = CTL_SMC_REG_REVR; - ct[i].procname = "reg_revr"; - ct[i].data = (void*)&(lp->ctl_reg_revr); - ct[i].maxlen = sizeof lp->ctl_reg_revr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_ERCVR - ++i; - ct[i].ctl_name = CTL_SMC_REG_ERCVR; - ct[i].procname = "reg_ercvr"; - ct[i].data = (void*)&(lp->ctl_reg_ercvr); - ct[i].maxlen = sizeof lp->ctl_reg_ercvr; - ct[i].mode = 0644; // Read by all, write by root - - // REG_EXTR - ++i; - ct[i].ctl_name = CTL_SMC_REG_EXTR; - ct[i].procname = "reg_extr"; - ct[i].data = (void*)&(lp->ctl_reg_extr); - ct[i].maxlen = sizeof lp->ctl_reg_extr; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Control - ++i; - ct[i].ctl_name = CTL_SMC_PHY_CTRL; - ct[i].procname = "phy_ctrl"; - ct[i].data = (void*)&(lp->ctl_phy_ctrl); - ct[i].maxlen = sizeof lp->ctl_phy_ctrl; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Status - ++i; - ct[i].ctl_name = CTL_SMC_PHY_STAT; - ct[i].procname = "phy_stat"; - ct[i].data = (void*)&(lp->ctl_phy_stat); - ct[i].maxlen = sizeof lp->ctl_phy_stat; - ct[i].mode = 0644; // Read by all, write by root - - // PHY ID1 - ++i; - ct[i].ctl_name = CTL_SMC_PHY_ID1; - ct[i].procname = "phy_id1"; - ct[i].data = (void*)&(lp->ctl_phy_id1); - ct[i].maxlen = sizeof lp->ctl_phy_id1; - ct[i].mode = 0644; // Read by all, write by root - - // PHY ID2 - ++i; - ct[i].ctl_name = CTL_SMC_PHY_ID2; - ct[i].procname = "phy_id2"; - ct[i].data = (void*)&(lp->ctl_phy_id2); - ct[i].maxlen = sizeof lp->ctl_phy_id2; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Advertise Capabilities - ++i; - ct[i].ctl_name = CTL_SMC_PHY_ADC; - ct[i].procname = "phy_adc"; - ct[i].data = (void*)&(lp->ctl_phy_adc); - ct[i].maxlen = sizeof lp->ctl_phy_adc; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Remote Capabilities - ++i; - ct[i].ctl_name = CTL_SMC_PHY_REMC; - ct[i].procname = "phy_remc"; - ct[i].data = (void*)&(lp->ctl_phy_remc); - ct[i].maxlen = sizeof lp->ctl_phy_remc; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Configuration 1 - ++i; - ct[i].ctl_name = CTL_SMC_PHY_CFG1; - ct[i].procname = "phy_cfg1"; - ct[i].data = (void*)&(lp->ctl_phy_cfg1); - ct[i].maxlen = sizeof lp->ctl_phy_cfg1; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Configuration 2 - ++i; - ct[i].ctl_name = CTL_SMC_PHY_CFG2; - ct[i].procname = "phy_cfg2"; - ct[i].data = (void*)&(lp->ctl_phy_cfg2); - ct[i].maxlen = sizeof lp->ctl_phy_cfg2; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Interrupt/Status Output - ++i; - ct[i].ctl_name = CTL_SMC_PHY_INT; - ct[i].procname = "phy_int"; - ct[i].data = (void*)&(lp->ctl_phy_int); - ct[i].maxlen = sizeof lp->ctl_phy_int; - ct[i].mode = 0644; // Read by all, write by root - - // PHY Interrupt/Status Mask - ++i; - ct[i].ctl_name = CTL_SMC_PHY_MASK; - ct[i].procname = "phy_mask"; - ct[i].data = (void*)&(lp->ctl_phy_mask); - ct[i].maxlen = sizeof lp->ctl_phy_mask; - ct[i].mode = 0644; // Read by all, write by root - -#endif // SMC_DEBUG - - // Register /proc/sys/dev/ethX - lp->sysctl_header = register_sysctl_table(lp->root_table, 1); -} - - -/*------------------------------------------------------------ - . Sysctl unregistration when driver is closed - .-------------------------------------------------------------*/ -static void smc_sysctl_unregister(struct net_device *dev) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - - unregister_sysctl_table(lp->sysctl_header); -} - -#endif /* endif CONFIG_SYSCTL */ - - -//---PHY CONTROL AND CONFIGURATION----------------------------------------- - -#if (SMC_DEBUG > 2 ) - -/*------------------------------------------------------------ - . Debugging function for viewing MII Management serial bitstream - .-------------------------------------------------------------*/ -static void smc_dump_mii_stream(byte* bits, int size) -{ - int i; - - printk("BIT#:"); - for (i = 0; i < size; ++i) - { - printk("%d", i%10); - } - - printk("\nMDOE:"); - for (i = 0; i < size; ++i) - { - if (bits[i] & MII_MDOE) - printk("1"); - else - printk("0"); - } - - printk("\nMDO :"); - for (i = 0; i < size; ++i) - { - if (bits[i] & MII_MDO) - printk("1"); - else - printk("0"); - } - - printk("\nMDI :"); - for (i = 0; i < size; ++i) - { - if (bits[i] & MII_MDI) - printk("1"); - else - printk("0"); - } - - printk("\n"); -} -#endif - -/*------------------------------------------------------------ - . Reads a register from the MII Management serial interface - .-------------------------------------------------------------*/ -static word smc_read_phy_register(int ioaddr, byte phyaddr, byte phyreg) -{ - int oldBank; - int i; - byte mask; - word mii_reg; - byte bits[64]; - int clk_idx = 0; - int input_idx; - word phydata; - - // 32 consecutive ones on MDO to establish sync - for (i = 0; i < 32; ++i) - bits[clk_idx++] = MII_MDOE | MII_MDO; - - // Start code <01> - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - // Read command <10> - bits[clk_idx++] = MII_MDOE | MII_MDO; - bits[clk_idx++] = MII_MDOE; - - // Output the PHY address, msb first - mask = (byte)0x10; - for (i = 0; i < 5; ++i) - { - if (phyaddr & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - // Shift to next lowest bit - mask >>= 1; - } - - // Output the phy register number, msb first - mask = (byte)0x10; - for (i = 0; i < 5; ++i) - { - if (phyreg & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - // Shift to next lowest bit - mask >>= 1; - } - - // Tristate and turnaround (2 bit times) - bits[clk_idx++] = 0; - //bits[clk_idx++] = 0; - - // Input starts at this bit time - input_idx = clk_idx; - - // Will input 16 bits - for (i = 0; i < 16; ++i) - bits[clk_idx++] = 0; - - // Final clock bit - bits[clk_idx++] = 0; - - // Save the current bank - oldBank = inw( ioaddr+BANK_SELECT ); - - // Select bank 3 - SMC_SELECT_BANK( 3 ); - - // Get the current MII register value - mii_reg = inw( ioaddr+MII_REG ); - - // Turn off all MII Interface bits - mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); - - // Clock all 64 cycles - for (i = 0; i < sizeof bits; ++i) - { - // Clock Low - output data - outw( mii_reg | bits[i], ioaddr+MII_REG ); - udelay(50); - - - // Clock Hi - input data - outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG ); - udelay(50); - bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI; - } - - // Return to idle state - // Set clock to low, data to low, and output tristated - outw( mii_reg, ioaddr+MII_REG ); - udelay(50); - - // Restore original bank select - SMC_SELECT_BANK( oldBank ); - - // Recover input data - phydata = 0; - for (i = 0; i < 16; ++i) - { - phydata <<= 1; - - if (bits[input_idx++] & MII_MDI) - phydata |= 0x0001; - } - -#if (SMC_DEBUG > 2 ) - printk("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", - phyaddr, phyreg, phydata); - smc_dump_mii_stream(bits, sizeof bits); -#endif - - return(phydata); -} - - -/*------------------------------------------------------------ - . Writes a register to the MII Management serial interface - .-------------------------------------------------------------*/ -static void smc_write_phy_register(int ioaddr, - byte phyaddr, byte phyreg, word phydata) -{ - int oldBank; - int i; - word mask; - word mii_reg; - byte bits[65]; - int clk_idx = 0; - - // 32 consecutive ones on MDO to establish sync - for (i = 0; i < 32; ++i) - bits[clk_idx++] = MII_MDOE | MII_MDO; - - // Start code <01> - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - // Write command <01> - bits[clk_idx++] = MII_MDOE; - bits[clk_idx++] = MII_MDOE | MII_MDO; - - // Output the PHY address, msb first - mask = (byte)0x10; - for (i = 0; i < 5; ++i) - { - if (phyaddr & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - // Shift to next lowest bit - mask >>= 1; - } - - // Output the phy register number, msb first - mask = (byte)0x10; - for (i = 0; i < 5; ++i) - { - if (phyreg & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - // Shift to next lowest bit - mask >>= 1; - } - - // Tristate and turnaround (2 bit times) - bits[clk_idx++] = 0; - bits[clk_idx++] = 0; - - // Write out 16 bits of data, msb first - mask = 0x8000; - for (i = 0; i < 16; ++i) - { - if (phydata & mask) - bits[clk_idx++] = MII_MDOE | MII_MDO; - else - bits[clk_idx++] = MII_MDOE; - - // Shift to next lowest bit - mask >>= 1; - } - - // Final clock bit (tristate) - bits[clk_idx++] = 0; - - // Save the current bank - oldBank = inw( ioaddr+BANK_SELECT ); - - // Select bank 3 - SMC_SELECT_BANK( 3 ); - - // Get the current MII register value - mii_reg = inw( ioaddr+MII_REG ); - - // Turn off all MII Interface bits - mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); - - // Clock all cycles - for (i = 0; i < sizeof bits; ++i) - { - // Clock Low - output data - outw( mii_reg | bits[i], ioaddr+MII_REG ); - udelay(50); - - - // Clock Hi - input data - outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG ); - udelay(50); - bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI; - } - - // Return to idle state - // Set clock to low, data to low, and output tristated - outw( mii_reg, ioaddr+MII_REG ); - udelay(50); - - // Restore original bank select - SMC_SELECT_BANK( oldBank ); - -#if (SMC_DEBUG > 2 ) - printk("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", - phyaddr, phyreg, phydata); - smc_dump_mii_stream(bits, sizeof bits); -#endif -} - - -/*------------------------------------------------------------ - . Finds and reports the PHY address - .-------------------------------------------------------------*/ -static int smc_detect_phy(struct net_device* dev) -{ - struct smc_local *lp = (struct smc_local *)dev->priv; - int ioaddr = dev->base_addr; - word phy_id1 = 0; - word phy_id2 = 0; - int phyaddr; - int found = 0; - - PRINTK3("%s:smc_detect_phy()\n", dev->name); - - // Scan all 32 PHY addresses if necessary - for (phyaddr = 0; phyaddr < 32; ++phyaddr) - { - // Read the PHY identifiers - phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG); - phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG); - - PRINTK3("%s: phy_id1=%x, phy_id2=%x\n", - dev->name, phy_id1, phy_id2); - - // Make sure it is a valid identifier - if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) && - (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) - { - if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) - { - // Save the PHY's address - lp->phyaddr = phyaddr; - found = 1; - break; - } - } - } - - if (!found) - { - PRINTK("%s: No PHY found\n", dev->name); - return(0); - } - - // Set the PHY type - if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) - { - lp->phytype = PHY_LAN83C183; - PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name); - } - - if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) - { - lp->phytype = PHY_LAN83C180; - PRINTK("%s: PHY=LAN83C180\n", dev->name); - } - - return(1); -} - -/*------------------------------------------------------------ - . Waits the specified number of milliseconds - kernel friendly - .-------------------------------------------------------------*/ -static void smc_wait_ms(unsigned int ms) -{ - - if (!in_interrupt()) - { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(1 + ms * HZ / 1000); - } - else - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1 + ms * HZ / 1000); - current->state = TASK_RUNNING; - } -} - -/*------------------------------------------------------------ - . Sets the PHY to a configuration as determined by the user - .-------------------------------------------------------------*/ -static int smc_phy_fixed(struct net_device* dev) -{ - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - byte phyaddr = lp->phyaddr; - word my_fixed_caps; - word cfg1; - - PRINTK3("%s:smc_phy_fixed()\n", dev->name); - - // Enter Link Disable state - cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG); - cfg1 |= PHY_CFG1_LNKDIS; - smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1); - - // Set our fixed capabilities - // Disable auto-negotiation - my_fixed_caps = 0; - - if (lp->ctl_rfduplx) - my_fixed_caps |= PHY_CNTL_DPLX; - - if (lp->ctl_rspeed == 100) - my_fixed_caps |= PHY_CNTL_SPEED; - - // Write our capabilities to the phy control register - smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps); - - // Re-Configure the Receive/Phy Control register - outw( lp->rpc_cur_mode, ioaddr + RPC_REG ); - - // Success - return(1); -} - - -/*------------------------------------------------------------ - . Configures the specified PHY using Autonegotiation. Calls - . smc_phy_fixed() if the user has requested a certain config. - .-------------------------------------------------------------*/ -static void smc_phy_configure(struct net_device* dev) -{ - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - int timeout; - byte phyaddr; - word my_phy_caps; // My PHY capabilities - word my_ad_caps; // My Advertised capabilities - word status; - int failed = 0; - - PRINTK3("%s:smc_program_phy()\n", dev->name); - - // Set the blocking flag - lp->autoneg_active = 1; - - // Find the address and type of our phy - if (!smc_detect_phy(dev)) - { - goto smc_phy_configure_exit; - } - - // Get the detected phy address - phyaddr = lp->phyaddr; - - // Reset the PHY, setting all other bits to zero - smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST); - - // Wait for the reset to complete, or time out - timeout = 6; // Wait up to 3 seconds - while (timeout--) - { - if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG) - & PHY_CNTL_RST)) - { - // reset complete - break; - } - - smc_wait_ms(500); // wait 500 millisecs - if (signal_pending(current)) // Exit anyway if signaled - { - PRINTK2("%s:PHY reset interrupted by signal\n", - dev->name); - timeout = 0; - break; - } - } - - if (timeout < 1) - { - PRINTK2("%s:PHY reset timed out\n", dev->name); - goto smc_phy_configure_exit; - } - - // Read PHY Register 18, Status Output - lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG); - - // Enable PHY Interrupts (for register 18) - // Interrupts listed here are disabled - smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG, - PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | - PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | - PHY_INT_SPDDET | PHY_INT_DPLXDET); - - /* Configure the Receive/Phy Control register */ - SMC_SELECT_BANK( 0 ); - outw( lp->rpc_cur_mode, ioaddr + RPC_REG ); - - // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG - my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); - my_ad_caps = PHY_AD_CSMA; // I am CSMA capable - - if (my_phy_caps & PHY_STAT_CAP_T4) - my_ad_caps |= PHY_AD_T4; - - if (my_phy_caps & PHY_STAT_CAP_TXF) - my_ad_caps |= PHY_AD_TX_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TXH) - my_ad_caps |= PHY_AD_TX_HDX; - - if (my_phy_caps & PHY_STAT_CAP_TF) - my_ad_caps |= PHY_AD_10_FDX; - - if (my_phy_caps & PHY_STAT_CAP_TH) - my_ad_caps |= PHY_AD_10_HDX; - - // Disable capabilities not selected by our user - if (lp->ctl_rspeed != 100) - { - my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX); - } - - if (!lp->ctl_rfduplx) - { - my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX); - } - - // Update our Auto-Neg Advertisement Register - smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps); - - PRINTK2("%s:phy caps=%x\n", dev->name, my_phy_caps); - PRINTK2("%s:phy advertised caps=%x\n", dev->name, my_ad_caps); - - // If the user requested no auto neg, then go set his request - if (!(lp->ctl_autoneg)) - { - smc_phy_fixed(dev); - goto smc_phy_configure_exit; - } - - // Restart auto-negotiation process in order to advertise my caps - smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST ); - - // Wait for the auto-negotiation to complete. This may take from - // 2 to 3 seconds. - // Wait for the reset to complete, or time out - timeout = 20; // Wait up to 10 seconds - while (timeout--) - { - status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); - if (status & PHY_STAT_ANEG_ACK) - { - // auto-negotiate complete - break; - } - - smc_wait_ms(500); // wait 500 millisecs - if (signal_pending(current)) // Exit anyway if signaled - { - printk(KERN_DEBUG - "%s:PHY auto-negotiate interrupted by signal\n", - dev->name); - timeout = 0; - break; - } - PRINTK3("%s:phy phy_fixed\n", dev->name); - - - // Restart auto-negotiation if remote fault - if (status & PHY_STAT_REM_FLT) - { - PRINTK2("%s:PHY remote fault detected\n", dev->name); - - // Restart auto-negotiation - PRINTK2("%s:PHY restarting auto-negotiation\n", - dev->name); - smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG, - PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST | - PHY_CNTL_SPEED | PHY_CNTL_DPLX); - } - } - - if (timeout < 1) - { - printk(KERN_DEBUG "%s:PHY auto-negotiate timed out\n", - dev->name); - PRINTK2("%s:PHY auto-negotiate timed out\n", dev->name); - failed = 1; - } - - // Fail if we detected an auto-negotiate remote fault - if (status & PHY_STAT_REM_FLT) - { - printk(KERN_DEBUG "%s:PHY remote fault detected\n", dev->name); - PRINTK2("%s:PHY remote fault detected\n", dev->name); - failed = 1; - } - - // The smc_phy_interrupt() routine will be called to update lastPhy18 - - // Set our sysctl parameters to match auto-negotiation results - if ( lp->lastPhy18 & PHY_INT_SPDDET ) - { - PRINTK2("%s:PHY 100BaseT\n", dev->name); - lp->rpc_cur_mode |= RPC_SPEED; - } - else - { - PRINTK2("%s:PHY 10BaseT\n", dev->name); - lp->rpc_cur_mode &= ~RPC_SPEED; - } - - if ( lp->lastPhy18 & PHY_INT_DPLXDET ) - { - PRINTK2("%s:PHY Full Duplex\n", dev->name); - lp->rpc_cur_mode |= RPC_DPLX; - } - else - { - PRINTK2("%s:PHY Half Duplex\n", dev->name); - lp->rpc_cur_mode &= ~RPC_DPLX; - } - - // Re-Configure the Receive/Phy Control register - outw( lp->rpc_cur_mode, ioaddr + RPC_REG ); - - smc_phy_configure_exit: - - // Exit auto-negotiation - lp->autoneg_active = 0; -} - - - -/************************************************************************* - . smc_phy_interrupt - . - . Purpose: Handle interrupts relating to PHY register 18. This is - . called from the "hard" interrupt handler. - . - ************************************************************************/ -static void smc_phy_interrupt(struct net_device* dev) -{ - int ioaddr = dev->base_addr; - struct smc_local *lp = (struct smc_local *)dev->priv; - byte phyaddr = lp->phyaddr; - word phy18; - - PRINTK2("%s: smc_phy_interrupt\n", dev->name); - - while (1) { - // Read PHY Register 18, Status Output - phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG); - - // Exit if not more changes - if (phy18 == lp->lastPhy18) - break; - -#if (SMC_DEBUG > 1 ) - - PRINTK2("%s: phy18=0x%x\n", dev->name, phy18); - PRINTK2("%s: lastPhy18=0x%x\n", dev->name, lp->lastPhy18); - - // Handle events - if ((phy18 & PHY_INT_LNKFAIL) != (lp->lastPhy18 & PHY_INT_LNKFAIL)) - { - PRINTK2("%s: PHY Link Fail=%x\n", dev->name, - phy18 & PHY_INT_LNKFAIL); - } - - if ((phy18 & PHY_INT_LOSSSYNC) != (lp->lastPhy18 & PHY_INT_LOSSSYNC)) - { - PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name, - phy18 & PHY_INT_LOSSSYNC); - } - - if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD)) - { - PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name, - phy18 & PHY_INT_CWRD); - } - - if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD)) - { - PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name, - phy18 & PHY_INT_SSD); - } - - if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD)) - { - PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name, - phy18 & PHY_INT_ESD); - } - - if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL)) - { - PRINTK2("%s: PHY Reverse Polarity Detected=%x\n", dev->name, - phy18 & PHY_INT_RPOL); - } - - if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB)) - { - PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name, - phy18 & PHY_INT_JAB); - } - - if ((phy18 & PHY_INT_SPDDET) != (lp->lastPhy18 & PHY_INT_SPDDET)) - { - PRINTK2("%s: PHY Speed Detect=%x\n", dev->name, - phy18 & PHY_INT_SPDDET); - } - - if ((phy18 & PHY_INT_DPLXDET) != (lp->lastPhy18 & PHY_INT_DPLXDET)) - { - PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name, - phy18 & PHY_INT_DPLXDET); - } -#endif - - // Update the last phy 18 variable - lp->lastPhy18 = phy18; - - } // end while -} - - diff -L arch/m32r/drivers/smc91111.copying -puN arch/m32r/drivers/smc91111.copying~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/smc91111.copying +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,352 +0,0 @@ - - NOTE! This copyright does *not* cover user programs that use kernel - services by normal system calls - this is merely considered normal use - of the kernel, and does *not* fall under the heading of "derived work". - Also note that the GPL below is copyrighted by the Free Software - Foundation, but the instance of code that it refers to (the Linux - kernel) is copyrighted by me and others who actually wrote it. - - Linus Torvalds - ----------------------------------------- - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff -L arch/m32r/drivers/smc91111.h -puN arch/m32r/drivers/smc91111.h~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/smc91111.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,570 +0,0 @@ -/*------------------------------------------------------------------------ - . smc91111.h - macros for the LAN91C111 Ethernet Driver - . - . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) - . Developed by Simple Network Magic Corporation (SNMC) - . Copyright (C) 1996 by Erik Stahlman (ES) - . - . This program is free software; you can redistribute it and/or modify - . it under the terms of the GNU General Public License as published by - . the Free Software Foundation; either version 2 of the License, or - . (at your option) any later version. - . - . This program is distributed in the hope that it will be useful, - . but WITHOUT ANY WARRANTY; without even the implied warranty of - . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - . GNU General Public License for more details. - . - . You should have received a copy of the GNU General Public License - . along with this program; if not, write to the Free Software - . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - . - . This file contains register information and access macros for - . the LAN91C111 single chip ethernet controller. It is a modified - . version of the smc9194.h file. - . - . Information contained in this file was obtained from the LAN91C111 - . manual from SMC. To get a copy, if you really want one, you can find - . information under www.smsc.com. - . - . Authors - . Erik Stahlman ( erik@vt.edu ) - . Daris A Nevil ( dnevil@snmc.com ) - . - . History - . 03/16/01 Daris A Nevil Modified for use with LAN91C111 device - . - ---------------------------------------------------------------------------*/ -#ifndef _SMC91111_H_ -#define _SMC91111_H_ - -/* I want some simple types */ - -typedef unsigned char byte; -typedef unsigned short word; -typedef unsigned long int dword; - - -/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ - -#define SMC_IO_EXTENT 16 - - -/*--------------------------------------------------------------- - . - . A description of the SMSC registers is probably in order here, - . although for details, the SMC datasheet is invaluable. - . - . Basically, the chip has 4 banks of registers ( 0 to 3 ), which - . are accessed by writing a number into the BANK_SELECT register - . ( I also use a SMC_SELECT_BANK macro for this ). - . - . The banks are configured so that for most purposes, bank 2 is all - . that is needed for simple run time tasks. - -----------------------------------------------------------------------*/ - -/* - . Bank Select Register: - . - . yyyy yyyy 0000 00xx - . xx = bank number - . yyyy yyyy = 0x33, for identification purposes. -*/ -#define BANK_SELECT 14 - -// Transmit Control Register -/* BANK 0 */ -#define TCR_REG 0x0000 // transmit control register -#define TCR_ENABLE 0x0001 // When 1 we can transmit -#define TCR_LOOP 0x0002 // Controls output pin LBK -#define TCR_FORCOL 0x0004 // When 1 will force a collision -#define TCR_PAD_EN 0x0080 // When 1 will pad tx frames < 64 bytes w/0 -#define TCR_NOCRC 0x0100 // When 1 will not append CRC to tx frames -#define TCR_MON_CSN 0x0400 // When 1 tx monitors carrier -#define TCR_FDUPLX 0x0800 // When 1 enables full duplex operation -#define TCR_STP_SQET 0x1000 // When 1 stops tx if Signal Quality Error -#define TCR_EPH_LOOP 0x2000 // When 1 enables EPH block loopback -#define TCR_SWFDUP 0x8000 // When 1 enables Switched Full Duplex mode - -#define TCR_CLEAR 0 /* do NOTHING */ -/* the default settings for the TCR register : */ -/* QUESTION: do I want to enable padding of short packets ? */ -#define TCR_DEFAULT TCR_ENABLE - - -// EPH Status Register -/* BANK 0 */ -#define EPH_STATUS_REG 0x0002 -#define ES_TX_SUC 0x0001 // Last TX was successful -#define ES_SNGL_COL 0x0002 // Single collision detected for last tx -#define ES_MUL_COL 0x0004 // Multiple collisions detected for last tx -#define ES_LTX_MULT 0x0008 // Last tx was a multicast -#define ES_16COL 0x0010 // 16 Collisions Reached -#define ES_SQET 0x0020 // Signal Quality Error Test -#define ES_LTXBRD 0x0040 // Last tx was a broadcast -#define ES_TXDEFR 0x0080 // Transmit Deferred -#define ES_LATCOL 0x0200 // Late collision detected on last tx -#define ES_LOSTCARR 0x0400 // Lost Carrier Sense -#define ES_EXC_DEF 0x0800 // Excessive Deferral -#define ES_CTR_ROL 0x1000 // Counter Roll Over indication -#define ES_LINK_OK 0x4000 // Driven by inverted value of nLNK pin -#define ES_TXUNRN 0x8000 // Tx Underrun - - -// Receive Control Register -/* BANK 0 */ -#define RCR_REG 0x0004 -#define RCR_RX_ABORT 0x0001 // Set if a rx frame was aborted -#define RCR_PRMS 0x0002 // Enable promiscuous mode -#define RCR_ALMUL 0x0004 // When set accepts all multicast frames -#define RCR_RXEN 0x0100 // IFF this is set, we can receive packets -#define RCR_STRIP_CRC 0x0200 // When set strips CRC from rx packets -#define RCR_ABORT_ENB 0x0200 // When set will abort rx on collision -#define RCR_FILT_CAR 0x0400 // When set filters leading 12 bit s of carrier -#define RCR_SOFTRST 0x8000 // resets the chip - -/* the normal settings for the RCR register : */ -#define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) -#define RCR_CLEAR 0x0 // set it to a base state - -// Counter Register -/* BANK 0 */ -#define COUNTER_REG 0x0006 - -// Memory Information Register -/* BANK 0 */ -#define MIR_REG 0x0008 - -// Receive/Phy Control Register -/* BANK 0 */ -#define RPC_REG 0x000A -#define RPC_SPEED 0x2000 // When 1 PHY is in 100Mbps mode. -#define RPC_DPLX 0x1000 // When 1 PHY is in Full-Duplex Mode -#define RPC_ANEG 0x0800 // When 1 PHY is in Auto-Negotiate Mode -#define RPC_LSXA_SHFT 5 // Bits to shift LS2A,LS1A,LS0A to lsb -#define RPC_LSXB_SHFT 2 // Bits to get LS2B,LS1B,LS0B to lsb -#define RPC_LED_100_10 (0x00) // LED = 100Mbps OR's with 10Mbps link detect -#define RPC_LED_RES (0x01) // LED = Reserved -#define RPC_LED_10 (0x02) // LED = 10Mbps link detect -#define RPC_LED_FD (0x03) // LED = Full Duplex Mode -#define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred -#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect -#define RPC_LED_TX (0x06) // LED = TX packet occurred -#define RPC_LED_RX (0x07) // LED = RX packet occurred -#if defined(__m32r__) -#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_TX_RX << RPC_LSXA_SHFT) | (RPC_LED_100_10 << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) -#else -#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) -#endif - -/* Bank 0 0x000C is reserved */ - -// Bank Select Register -/* All Banks */ -#define BSR_REG 0x000E - - -// Configuration Reg -/* BANK 1 */ -#define CONFIG_REG 0x0000 -#define CONFIG_EXT_PHY 0x0200 // 1=external MII, 0=internal Phy -#define CONFIG_GPCNTRL 0x0400 // Inverse value drives pin nCNTRL -#define CONFIG_NO_WAIT 0x1000 // When 1 no extra wait states on ISA bus -#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode. - -// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low -#define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) - - -// Base Address Register -/* BANK 1 */ -#define BASE_REG 0x0002 - - -// Individual Address Registers -/* BANK 1 */ -#define ADDR0_REG 0x0004 -#define ADDR1_REG 0x0006 -#define ADDR2_REG 0x0008 - - -// General Purpose Register -/* BANK 1 */ -#define GP_REG 0x000A - - -// Control Register -/* BANK 1 */ -#define CTL_REG 0x000C -#define CTL_RCV_BAD 0x4000 // When 1 bad CRC packets are received -#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically -#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt -#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt -#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt -#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store -#define CTL_RELOAD 0x0002 // When set reads EEPROM into registers -#define CTL_STORE 0x0001 // When set stores registers into EEPROM - - -// MMU Command Register -/* BANK 2 */ -#define MMU_CMD_REG 0x0000 -#define MC_BUSY 1 // When 1 the last release has not completed -#define MC_NOP (0<<5) // No Op -#define MC_ALLOC (1<<5) // OR with number of 256 byte packets -#define MC_RESET (2<<5) // Reset MMU to initial state -#define MC_REMOVE (3<<5) // Remove the current rx packet -#define MC_RELEASE (4<<5) // Remove and release the current rx packet -#define MC_FREEPKT (5<<5) // Release packet in PNR register -#define MC_ENQUEUE (6<<5) // Enqueue the packet for transmit -#define MC_RSTTXFIFO (7<<5) // Reset the TX FIFOs - - -// Packet Number Register -/* BANK 2 */ -#define PN_REG 0x0002 - - -// Allocation Result Register -/* BANK 2 */ -#define AR_REG 0x0003 -#define AR_FAILED 0x80 // Alocation Failed - - -// RX FIFO Ports Register -/* BANK 2 */ -#define RXFIFO_REG 0x0004 // Must be read as a word -#define RXFIFO_REMPTY 0x8000 // RX FIFO Empty - - -// TX FIFO Ports Register -/* BANK 2 */ -#define TXFIFO_REG RXFIFO_REG // Must be read as a word -#define TXFIFO_TEMPTY 0x80 // TX FIFO Empty - - -// Pointer Register -/* BANK 2 */ -#define PTR_REG 0x0006 -#define PTR_RCV 0x8000 // 1=Receive area, 0=Transmit area -#define PTR_AUTOINC 0x4000 // Auto increment the pointer on each access -#define PTR_READ 0x2000 // When 1 the operation is a read - - -// Data Register -/* BANK 2 */ -#define DATA_REG 0x0008 - - -// Interrupt Status/Acknowledge Register -/* BANK 2 */ -#define INT_REG 0x000C - - -// Interrupt Mask Register -/* BANK 2 */ -#define IM_REG 0x000D -#define IM_MDINT 0x80 // PHY MI Register 18 Interrupt -#define IM_ERCV_INT 0x40 // Early Receive Interrupt -#define IM_EPH_INT 0x20 // Set by Etheret Protocol Handler section -#define IM_RX_OVRN_INT 0x10 // Set by Receiver Overruns -#define IM_ALLOC_INT 0x08 // Set when allocation request is completed -#define IM_TX_EMPTY_INT 0x04 // Set if the TX FIFO goes empty -#define IM_TX_INT 0x02 // Transmit Interrrupt -#define IM_RCV_INT 0x01 // Receive Interrupt - - -// Multicast Table Registers -/* BANK 3 */ -#define MCAST_REG1 0x0000 -#define MCAST_REG2 0x0002 -#define MCAST_REG3 0x0004 -#define MCAST_REG4 0x0006 - - -// Management Interface Register (MII) -/* BANK 3 */ -#define MII_REG 0x0008 -#define MII_MSK_CRS100 0x4000 // Disables CRS100 detection during tx half dup -#define MII_MDOE 0x0008 // MII Output Enable -#define MII_MCLK 0x0004 // MII Clock, pin MDCLK -#define MII_MDI 0x0002 // MII Input, pin MDI -#define MII_MDO 0x0001 // MII Output, pin MDO - - -// Revision Register -/* BANK 3 */ -#define REV_REG 0x000A /* ( hi: chip id low: rev # ) */ - - -// Early RCV Register -/* BANK 3 */ -/* this is NOT on SMC9192 */ -#define ERCV_REG 0x000C -#define ERCV_RCV_DISCRD 0x0080 // When 1 discards a packet being received -#define ERCV_THRESHOLD 0x001F // ERCV Threshold Mask - -// External Register -/* BANK 7 */ -#define EXT_REG 0x0000 - - -#define CHIP_9192 3 -#define CHIP_9194 4 -#define CHIP_9195 5 -#define CHIP_9196 6 -#define CHIP_91100 7 -#define CHIP_91100FD 8 -#define CHIP_91111FD 9 - -static const char * chip_ids[ 15 ] = { - NULL, NULL, NULL, - /* 3 */ "SMC91C90/91C92", - /* 4 */ "SMC91C94", - /* 5 */ "SMC91C95", - /* 6 */ "SMC91C96", - /* 7 */ "SMC91C100", - /* 8 */ "SMC91C100FD", - /* 9 */ "SMC91C11xFD", - NULL, NULL, - NULL, NULL, NULL}; - -/* - . Transmit status bits -*/ -#define TS_SUCCESS 0x0001 -#define TS_LOSTCAR 0x0400 -#define TS_LATCOL 0x0200 -#define TS_16COL 0x0010 - -/* - . Receive status bits -*/ -#define RS_ALGNERR 0x8000 -#define RS_BRODCAST 0x4000 -#define RS_BADCRC 0x2000 -#define RS_ODDFRAME 0x1000 // bug: the LAN91C111 never sets this on receive -#define RS_TOOLONG 0x0800 -#define RS_TOOSHORT 0x0400 -#define RS_MULTICAST 0x0001 -#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) - - -// PHY Types -enum { - PHY_LAN83C183 = 1, // LAN91C111 Internal PHY - PHY_LAN83C180 -}; - - -// PHY Register Addresses (LAN91C111 Internal PHY) - -// PHY Control Register -#define PHY_CNTL_REG 0x00 -#define PHY_CNTL_RST 0x8000 // 1=PHY Reset -#define PHY_CNTL_LPBK 0x4000 // 1=PHY Loopback -#define PHY_CNTL_SPEED 0x2000 // 1=100Mbps, 0=10Mpbs -#define PHY_CNTL_ANEG_EN 0x1000 // 1=Enable Auto negotiation -#define PHY_CNTL_PDN 0x0800 // 1=PHY Power Down mode -#define PHY_CNTL_MII_DIS 0x0400 // 1=MII 4 bit interface disabled -#define PHY_CNTL_ANEG_RST 0x0200 // 1=Reset Auto negotiate -#define PHY_CNTL_DPLX 0x0100 // 1=Full Duplex, 0=Half Duplex -#define PHY_CNTL_COLTST 0x0080 // 1= MII Colision Test - -// PHY Status Register -#define PHY_STAT_REG 0x01 -#define PHY_STAT_CAP_T4 0x8000 // 1=100Base-T4 capable -#define PHY_STAT_CAP_TXF 0x4000 // 1=100Base-X full duplex capable -#define PHY_STAT_CAP_TXH 0x2000 // 1=100Base-X half duplex capable -#define PHY_STAT_CAP_TF 0x1000 // 1=10Mbps full duplex capable -#define PHY_STAT_CAP_TH 0x0800 // 1=10Mbps half duplex capable -#define PHY_STAT_CAP_SUPR 0x0040 // 1=recv mgmt frames with not preamble -#define PHY_STAT_ANEG_ACK 0x0020 // 1=ANEG has completed -#define PHY_STAT_REM_FLT 0x0010 // 1=Remote Fault detected -#define PHY_STAT_CAP_ANEG 0x0008 // 1=Auto negotiate capable -#define PHY_STAT_LINK 0x0004 // 1=valid link -#define PHY_STAT_JAB 0x0002 // 1=10Mbps jabber condition -#define PHY_STAT_EXREG 0x0001 // 1=extended registers implemented - -// PHY Identifier Registers -#define PHY_ID1_REG 0x02 // PHY Identifier 1 -#define PHY_ID2_REG 0x03 // PHY Identifier 2 - -// PHY Auto-Negotiation Advertisement Register -#define PHY_AD_REG 0x04 -#define PHY_AD_NP 0x8000 // 1=PHY requests exchange of Next Page -#define PHY_AD_ACK 0x4000 // 1=got link code word from remote -#define PHY_AD_RF 0x2000 // 1=advertise remote fault -#define PHY_AD_T4 0x0200 // 1=PHY is capable of 100Base-T4 -#define PHY_AD_TX_FDX 0x0100 // 1=PHY is capable of 100Base-TX FDPLX -#define PHY_AD_TX_HDX 0x0080 // 1=PHY is capable of 100Base-TX HDPLX -#define PHY_AD_10_FDX 0x0040 // 1=PHY is capable of 10Base-T FDPLX -#define PHY_AD_10_HDX 0x0020 // 1=PHY is capable of 10Base-T HDPLX -#define PHY_AD_CSMA 0x0001 // 1=PHY is capable of 802.3 CMSA - -// PHY Auto-negotiation Remote End Capability Register -#define PHY_RMT_REG 0x05 -// Uses same bit definitions as PHY_AD_REG - -// PHY Configuration Register 1 -#define PHY_CFG1_REG 0x10 -#define PHY_CFG1_LNKDIS 0x8000 // 1=Rx Link Detect Function disabled -#define PHY_CFG1_XMTDIS 0x4000 // 1=TP Transmitter Disabled -#define PHY_CFG1_XMTPDN 0x2000 // 1=TP Transmitter Powered Down -#define PHY_CFG1_BYPSCR 0x0400 // 1=Bypass scrambler/descrambler -#define PHY_CFG1_UNSCDS 0x0200 // 1=Unscramble Idle Reception Disable -#define PHY_CFG1_EQLZR 0x0100 // 1=Rx Equalizer Disabled -#define PHY_CFG1_CABLE 0x0080 // 1=STP(150ohm), 0=UTP(100ohm) -#define PHY_CFG1_RLVL0 0x0040 // 1=Rx Squelch level reduced by 4.5db -#define PHY_CFG1_TLVL_SHIFT 2 // Transmit Output Level Adjust -#define PHY_CFG1_TLVL_MASK 0x003C -#define PHY_CFG1_TRF_MASK 0x0003 // Transmitter Rise/Fall time - - -// PHY Configuration Register 2 -#define PHY_CFG2_REG 0x11 -#define PHY_CFG2_APOLDIS 0x0020 // 1=Auto Polarity Correction disabled -#define PHY_CFG2_JABDIS 0x0010 // 1=Jabber disabled -#define PHY_CFG2_MREG 0x0008 // 1=Multiple register access (MII mgt) -#define PHY_CFG2_INTMDIO 0x0004 // 1=Interrupt signaled with MDIO pulseo - -// PHY Status Output (and Interrupt status) Register -#define PHY_INT_REG 0x12 // Status Output (Interrupt Status) -#define PHY_INT_INT 0x8000 // 1=bits have changed since last read -#define PHY_INT_LNKFAIL 0x4000 // 1=Link Not detected -#define PHY_INT_LOSSSYNC 0x2000 // 1=Descrambler has lost sync -#define PHY_INT_CWRD 0x1000 // 1=Invalid 4B5B code detected on rx -#define PHY_INT_SSD 0x0800 // 1=No Start Of Stream detected on rx -#define PHY_INT_ESD 0x0400 // 1=No End Of Stream detected on rx -#define PHY_INT_RPOL 0x0200 // 1=Reverse Polarity detected -#define PHY_INT_JAB 0x0100 // 1=Jabber detected -#define PHY_INT_SPDDET 0x0080 // 1=100Base-TX mode, 0=10Base-T mode -#define PHY_INT_DPLXDET 0x0040 // 1=Device in Full Duplex - -// PHY Interrupt/Status Mask Register -#define PHY_MASK_REG 0x13 // Interrupt Mask -// Uses the same bit definitions as PHY_INT_REG - - - -/*------------------------------------------------------------------------- - . I define some macros to make it easier to do somewhat common - . or slightly complicated, repeated tasks. - --------------------------------------------------------------------------*/ - -/* select a register bank, 0 to 3 */ - -#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT ); } - -/* this enables an interrupt in the interrupt mask register */ -#define SMC_ENABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = inb( ioaddr + IM_REG );\ - mask |= (x);\ - outb( mask, ioaddr + IM_REG ); \ -} - -/* this disables an interrupt from the interrupt mask register */ - -#define SMC_DISABLE_INT(x) {\ - unsigned char mask;\ - SMC_SELECT_BANK(2);\ - mask = inb( ioaddr + IM_REG );\ - mask &= ~(x);\ - outb( mask, ioaddr + IM_REG ); \ -} - -/*---------------------------------------------------------------------- - . Define the interrupts that I want to receive from the card - . - . I want: - . IM_EPH_INT, for nasty errors - . IM_RCV_INT, for happy received packets - . IM_RX_OVRN_INT, because I have to kick the receiver - . IM_MDINT, for PHY Register 18 Status Changes - --------------------------------------------------------------------------*/ -#define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \ - IM_MDINT) - - -#ifdef CONFIG_SYSCTL - - -/* - * Declarations for the sysctl interface, which allows users the ability to - * control the finer aspects of the LAN91C111 chip. Since the smc - * module currently registers its sysctl table dynamically, the sysctl path - * for module FOO is /proc/sys/dev/ethX/FOO - */ -#define CTL_SMC (CTL_BUS+1389) // arbitrary and hopefully unused - -enum { - CTL_SMC_INFO = 1, // Sysctl files information - CTL_SMC_SWVER, // Driver Software Version Info - CTL_SMC_SWFDUP, // Switched Full Duplex Mode - CTL_SMC_EPHLOOP, // EPH Block Internal Loopback - CTL_SMC_MIIOP, // MII Operation - CTL_SMC_AUTONEG, // Auto-negotiate Mode - CTL_SMC_RFDUPLX, // Request Full Duplex Mode - CTL_SMC_RSPEED, // Request Speed Selection - CTL_SMC_AFDUPLX, // Actual Full Duplex Mode - CTL_SMC_ASPEED, // Actual Speed Selection - CTL_SMC_LNKFAIL, // Link Failed - CTL_SMC_FORCOL, // Force a Collision - CTL_SMC_FILTCAR, // Filter Carrier - CTL_SMC_FREEMEM, // Free Buffer Memory - CTL_SMC_TOTMEM, // Total Buffer Memory - CTL_SMC_LEDA, // Output of LED-A - CTL_SMC_LEDB, // Output of LED-B - CTL_SMC_CHIPREV, // LAN91C111 Chip Revision ID -#ifdef SMC_DEBUG - // Register access for debugging - CTL_SMC_REG_BSR, // Bank Select - CTL_SMC_REG_TCR, // Transmit Control - CTL_SMC_REG_ESR, // EPH Status - CTL_SMC_REG_RCR, // Receive Control - CTL_SMC_REG_CTRR, // Counter - CTL_SMC_REG_MIR, // Memory Information - CTL_SMC_REG_RPCR, // Receive/Phy Control - CTL_SMC_REG_CFGR, // Configuration - CTL_SMC_REG_BAR, // Base Address - CTL_SMC_REG_IAR0, // Individual Address 0 - CTL_SMC_REG_IAR1, // Individual Address 1 - CTL_SMC_REG_IAR2, // Individual Address 2 - CTL_SMC_REG_GPR, // General Purpose - CTL_SMC_REG_CTLR, // Control - CTL_SMC_REG_MCR, // MMU Command - CTL_SMC_REG_PNR, // Packet Number - CTL_SMC_REG_FPR, // FIFO Ports - CTL_SMC_REG_PTR, // Pointer - CTL_SMC_REG_DR, // Data - CTL_SMC_REG_ISR, // Interrupt Status - CTL_SMC_REG_MTR1, // Multicast Table Entry 1 - CTL_SMC_REG_MTR2, // Multicast Table Entry 2 - CTL_SMC_REG_MTR3, // Multicast Table Entry 3 - CTL_SMC_REG_MTR4, // Multicast Table Entry 4 - CTL_SMC_REG_MIIR, // Management Interface - CTL_SMC_REG_REVR, // Revision - CTL_SMC_REG_ERCVR, // Early RCV - CTL_SMC_REG_EXTR, // External - CTL_SMC_PHY_CTRL, // PHY Control - CTL_SMC_PHY_STAT, // PHY Status - CTL_SMC_PHY_ID1, // PHY ID1 - CTL_SMC_PHY_ID2, // PHY ID2 - CTL_SMC_PHY_ADC, // PHY Advertise Capability - CTL_SMC_PHY_REMC, // PHY Advertise Capability - CTL_SMC_PHY_CFG1, // PHY Configuration 1 - CTL_SMC_PHY_CFG2, // PHY Configuration 2 - CTL_SMC_PHY_INT, // PHY Interrupt/Status Output - CTL_SMC_PHY_MASK, // PHY Interrupt/Status Mask -#endif - // --------------------------------------------------- - CTL_SMC_LAST_ENTRY // Add new entries above the line -}; - -#endif // CONFIG_SYSCTL - -#endif /* _SMC_91111_H_ */ - - diff -L arch/m32r/drivers/smc91111.readme.txt -puN arch/m32r/drivers/smc91111.readme.txt~m32r-remove-network-drivers /dev/null --- 25/arch/m32r/drivers/smc91111.readme.txt +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,561 +0,0 @@ -SMSC LAN91C111 Driver -Revision 2.0 -9/24/01 -Copyright (C) 2001 Standard Microsystems Corporation (SMSC) -Copyright (C) 1996 by Erik Stahlman (ES) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -This file contains the instructions, test methods, and caveats for the -smc91111.c driver. You may not be using the driver without reading this file. - -Driver Description: -=================== -This driver has been modified to work on kernel 2.4. And it also contains the -latest SMSC updates for the Odd Byte issue. Important thing to note about this -is that, this driver might not compile on kernel version older than 2.4. - Please visit the SMSC website (http://www.smsc.com) for latest updates on the -drivers. - - -Things to note about installation: -================================== - - 1. This is designed to be compiled and loaded as a module. While putting - it into your kernel should be possible, it has not yet been tested. - - 2. The driver will only load on recent kernels because of changes to - the network driver interface. I have compiled this under kernel 2.4. - - - 3. To compile, run 'make' . - - 4. Loading the driver: - - use: insmod smc91111.o - optional parameters: - io=0x### : your base address - irq=## : your irq - nowait=x : 0 for standard I/O access (IOCHRDY wait states) - 1 for fast access (no IOCHRDY wait states) - - 5. To allow automatic loading and intialization of the driver at boot-up - add the following line to /etc/modules.conf (in RedHat 7.0): - - alias eth0 smc91111 - options eth0 io=0x### irq=## - - See the man pages on module.conf. You must also be sure to copy the - smc91111.o file to the modules directory: - - su - cd /lib/modules/YOUR_CURRENT_KERNEL_VERSION/net - cp 'directory where the file resides'/smc91111.o . - chown root:root smc91111.o - chmod a+r smc91111.o - - Then you must update the module dependencies (as root): - - /sbin/depmod - - - -Advanced Features: -================== - -If your Linux Kernel was compiled with the configuration options CONFIG_PROC_FS -and CONFIG_SYSCTL enabled then the smc91111 driver provides several sysctl -files for accessing extended features. These files can be found in -/proc/sys/dev/ethX, where X is the interface number of the ethernet port. For -example, if your SMC91C111 card is the only one in the system then your sysctl -files will be located at /proc/sys/dev/eth0. - -The following lists the files supported by the driver. - - sysctl file Description -------------- -------------------------------------------------------------- - info Prints a list of supported files along with a terse - description of each one. - - swver Prints the software version information of the driver. - - autoneg When set to 1 enables auto negotiation mode. The LAN91C111 - supports auto negotiation per IEEE 802.3 Clause 28. When auto - negotiation is set the files "rspeed" and "rfduplx" (below) - limit what capabilities are broadcast to the remote end. - When "autoneg" is set to 0 the auto-negotiation feature - is disabled, and the speed and duplex can be controlled - directly and immediately with "rspeed" and "rfduplx". - You can change the value of this file by issuing the command - "echo 0 > autoneg", assuming that you are in the directory - /proc/sys/dev/ethX. - The default value of "autoneg" is 1. - - aspeed Reports the actual speed of the link. This file is read-only. - - afduplx Reports the actual duplex of the link. A value of 1 indicates - the link is currently operating in full duplex. This file - is read-only. - - rspeed Requested speed, controls the speed of the interface. The - behavior invoked by this file depends on the value of - the "autoneg" file. See the "autoneg" description above. A value - of 100 indicates 100Mpbs, and a speed of 10 indicates 10Mbps. - You cannot change the value of "rspeed" when "autoneg" is - set to 1. You can issue the following commands to restrict - the LAN91C111 to 10Mbps operation: - cd /proc/sys/dev/eth0 - echo 0 > autoneg - echo 10 > speed - echo 1 > autoneg - The default value of "speed" is 100. - - rfduplx Requested duplex, controls the duplex operation of the - interface. The behavior invoked by this file depends on the - value of the "autoneg" file. See the "autoneg" description - above. A value of 1 indicates full duplex, while a value of 0 - indicates half duplex operation. You cannot change the value - of "rfduplx" when "autoneg" is set to 1. The default value of - "rfduplx" is 1. - - lnkfail When 1 indicates the PHY link is in a failure state (i.e. - not connected to a valid LAN). A value of 0 indicates - normal operation. - - miiop When set to 1 selects an external PHY. This feature has not - yet been tested. The default value of "miiop" is 0. - - swfdup When set to 1 enables Switched Full Duplex Operation. This - is to be used only when miiop is set to 1 (according to the - LAN91C111 documentation). This feature has not yet been - tested. The default value of "swfdup" is 0. - - ephloop When set to 1 enables a loopback in the EPH block. This feature - has not yet been tested. The default value of "ephloop" is 0. - - forcol When set to 1 forces a collision. This feature has not yet been - tested. The default value of "forcol" is 0. - - filtcar When set to 1 the LAN91C111 filters the leading edge of carrier - sense for 12 bit times. This feature has not yet been tested. - The default value of "filtcar" is 0. - - freemem Reports the amount of buffer memory currently free, in bytes. - - totmem Reports the total amount of buffer memory contained in the - LAN91C111, in bytes. - - leda Reports and controls which line condition is reported on - LEDA. I tested this feature with the SMSC EVB111-ISA board. - LED A on this card is green and is labelled "100". This - file accepts values from 0 thru 7. - - Value Line Condition Reported - ----- ---------------------------------------------- - 0 Logical OR of 100Mbps and 10Mbps link detected - 1 Reserved - 2 10Mpbs link detected - 3 Full Duplex Mode Enabled - 4 Transmit or Receive packet occurred - 5 100Mbps Link Detected - 6 Transmit packet occurred - 7 Receive packet occurred - - The default value of "leda" is 5. - - ledb Reports and controls which line condition is reported on - LEDB. I tested this feature with the SMSC EVB111-ISA board. - LED B on this card is yellow and is labelled "FD". This - file accepts values from 0 thru 7 (see above). - The default value of "ledb" is 3. - - chiprev Reports the chip revision number of the LAN91C111. - - -Testing Methodology and Report: -=============================== - -I tested the smc91111.c driver using RedHat 7.1. The version I tested with -came with kernel version 2.4.2. I updated the gcc tools because of -known bugs in this version of the RedHat distribution. It should not have -made a difference though, as the module is actually compiled using the "kgcc" -compiler provided by RedHat 7.1 (you have to manually install the kgcc rpm -from the CDROM). - -I used two machines to perform tests. The first is an AST Bravo MS-T PRO 6200, -Model 2500C. It contains a PentiumPro w/integrated 256KB L2 cache, 64Mbytes of -EDO DRAM, and a 2.5GB EIDE hard drive. - -The second machine is a generic Pentium II running at 360MHz. It contains -64Mbytes of SDRAM, and a 30GB hard drive. I used a NetGear FA311 PCI Ethernet -card in this machine. I compiled and installed the fa311.c driver provided -with the card. - -I tested in two configurations. The first was in isolation, where the two -machines were connected to each other with a CAT5 crossover cable. The second -configuration connected both machines to a local area network running at -10Mbps. This lan containes three Windows machines and an Efficient Networks -SpeedStream router, connected to the Internet through an IDSL (today it is -served by Northpoint, tomorrow it is serviced by ????) - -Test Scenerio #1 -Testing in Isolated Network - -The PentiumPro machine with the EVB111-ISA card is named "LOCAL", with IP address 216.36.95.135, netmask 255.255.255.240. - -The PentiumII machine with the NetGear FA311 is named "REMOTE", with IP address of 216.36.95.134, netmask 255.255.255.240. - -1. Bring the interface up. - - The insmod and ifconfig programs must be executed as root. - - LOCAL: /sbin/insmod smc91111.o - Check /var/log/messages (at end) for results. You should see the I/O address - and IRQ assigned to the card by the auto probe function. - - LOCAL: /sbin/ifconfig eth0 216.36.95.135 netmask 255.255.255.240 - Verify that the interace is up by checking the results of ifconfig: - - LOCAL: /sbin/ifconfig - Verify that the Ethernet MAC address reported by ifconfig looks reasonable. - The card I tested with contained the address "00:80:0F:6A:00:00". Beware - of addresses with all zeros, all ones, or repeating bytes. - - Test Result: Passed - - -2. Ping Remote Side - - LOCAL: ping -c5 216.36.95.134 - Verify that 5 pings were returned. - - Test Result: Passed - - -3. Check sysctl variables - - LOCAL: cd /proc/sys/dev/eth0 - LOCAL: ls - Verify that the following files are shown: - afduplx autoneg ephloop forcol info ledb miiop rspeed swver - aspeed chiprev filtcar freemem leda lnkfail rfduplx swfdup totmem - - LOCAL: more autoneg - Verify that the value printed is 1. - - LOCAL: more rspeed - Verify that the value printed is 100. - - LOCAL: more rfduplx - Verify that the value printed is 1. - - LOCAL: more aspeed - Verify that the value printed is 100. - - LOCAL: more afduplx - Verify that the value printed is 1. - - LOCAL: more lnkfail - Verify that the value printed is 0. - - LOCAL: more totmem - Verify that the value printed is 8192. - - LOCAL: more freemem - Verify that the value printed is 8192. - - LOCAL: more leda - Verify that the value printed is 5 - - LOCAL: more ledb - Verify that the value printed is 3 - - Test Result: Passed - - -4. Check LEDs - - You may not be able to do this depending on the LEDs supported on your - card. - - Verify that the "100" LED is on, indicating a 100Mbps connection. - - Verify that the "FD" LED is on, indicating Full-Duplex connection. - - Test Result: Passed - - -5. Check Transport - use ftp to transport a large file across the ethernet - - Obtain a large file, preferably several megabytes in size. I used the - file XFree86-4.0.1-1.i386.rpm from Disk 1 of the RedHat 7.0 distribution - because it was 15Mbytes in size. - - REMOTE: ftp 216.36.95.135 - REMOTE: bin - REMOTE: put large_file - REMOTE: get large_file large_file_ftp - REMOTE: quit - REMOTE: diff large_file large_file_ftp - Verify that the transfer occurred correctly, and that the file was not - modified after transport. - - Test Result: Passed - - -6. Disable Auto-Negotiate, Force Half Duplex, 100Mbps - - The files in /proc/sys/dev/ethX can only be changed by root. - - LOCAL: echo 0 > autoneg - Wait 5 seconds. - LOCAL: echo 0 > rfduplx - Wait 5 seconds. - LOCAL: more rfduplx - Verify that the result printed is 0. - LOCAL: more afduplx - Verify that the result printed is 0. Verify that the "100" LED is on, - and the "FD" LED is off. - Perform Test #2 (Ping Remote Side) to verify connection. - Perform Test #5 (Check Transport). - - Test Result: Passed - - -7. Eanble Auto-Negotiate, Advertising Half Duplex, 100Mbps - - LOCAL: echo 1 > autoneg - Wait 5 seconds. - Verify that the "100" LED is on, and the "FD" LED is off. - LOCAL: more autoneg - Verify that the result printed is 1. - LOCAL: more afduplx - Verify that the result printed is 0. - LOCAL: more aspeed - Verify that the result printed is 100. - Perform Test #2 (Ping Remote Side) to verify connection. - LOCAL: more lnkfail - Verify that the result printed is 0. - Remove the ethernet cable from the RJ-45 connector. - LOCAL: more lnkfail - Verify that the result printed is 1. - Reinsert the ethernet cable into the RJ-45 connector. - LOCAL: more lnkfail - Verify that the result printed is 0. - LOCAL: more afduplx - Verify that the result printed is 0. - LOCAL: more aspeed - Verify that the result printed is 100. - Perform Test #2 (Ping Remote Side) to verify connection. - - Test Result: Passed - - -8. Force Half Duplex, 10Mbps - - LOCAL: echo 0 > autoneg - Wait 5 seconds. - LOCAL: echo 10 > rspeed - Wait 5 seconds. - LOCAL: more aspeed - Verify that the result printed is 10. Verify that the "100" LED is off, - and the "FD" LED is off. - LOCAL: more afduplx - Verify that the result printed is 0. - Perform Test #2 (Ping Remote Side) to verify connection. - Perform Test #5 (Check Transport). - - Test Result: Passed - - -9. Eanble Auto-Negotiate, Advertising Half Duplex, 10Mbps - - LOCAL: echo 1 > autoneg - Wait 5 seconds. - Verify that the "100" LED is off, and the "FD" LED is off. - LOCAL: more autoneg - Verify that the result printed is 1. - LOCAL: more afduplx - Verify that the result printed is 0. - LOCAL: more aspeed - Verify that the result printed is 10. - Perform Test #2 (Ping Remote Side) to verify connection. - LOCAL: more lnkfail - Verify that the result printed is 0. - Remove the ethernet cable from the RJ-45 connector. - LOCAL: more lnkfail - Verify that the result printed is 1. - Reinsert the ethernet cable into the RJ-45 connector. - LOCAL: more lnkfail - Verify that the result printed is 0. - LOCAL: more afduplx - Verify that the result printed is 0. - LOCAL: more aspeed - Verify that the result printed is 10. - Perform Test #2 (Ping Remote Side) to verify connection. - - Test Result: Passed - - -10. Force Full Duplex, 10Mbps - - LOCAL: echo 0 > autoneg - Wait 5 seconds. - LOCAL: echo 1 > rfduplx - Wait 5 seconds. - LOCAL: more afduplx - Verify that the result printed is 1. Verify that the "100" LED is off, - and the "FD" LED is on. - LOCAL: more aspeed - Verify that the result printed is 10. - Perform Test #2 (Ping Remote Side) to verify connection. - Perform Test #5 (Check Transport). - - Test Result: Passed - - -11. Eanble Auto-Negotiate, Advertising Full Duplex, 10Mbps - - LOCAL: echo 1 > autoneg - Wait 5 seconds. - Verify that the "100" LED is off, and the "FD" LED is on. - LOCAL: more autoneg - Verify that the result printed is 1. - LOCAL: more afduplx - Verify that the result printed is 1. - LOCAL: more aspeed - Verify that the result printed is 10. - Perform Test #2 (Ping Remote Side) to verify connection. - - Test Result: Passed - - - -12. Return to Full Duplex, 100Mbps - - LOCAL: echo 0 > autoneg - Wait 5 seconds. - LOCAL: echo 1 > rfduplx - Wait 5 seconds. - LOCAL: more afduplx - Verify that the result printed is 1. - LOCAL: echo 100 > rspeed - Wait 5 seconds. - LOCAL: more espeed - Verify that the result printed is 100. - Verify that the "100" LED is on, and the "FD" LED is on. - Perform Test #2 (Ping Remote Side) to verify connection. - LOCAL: echo 1 > autoneg - Wait 5 seconds. - Verify that the "100" LED is on, and the "FD" LED is on. - LOCAL: more autoneg - Verify that the result printed is 1. - LOCAL: more afduplx - Verify that the result printed is 1. - LOCAL: more aspeed - Verify that the result printed is 100. - Perform Test #2 (Ping Remote Side) to verify connection. - - Test Result: Passed - - - -Test Scenerio #2 -Testing in a Mixed-Mode 10Mbps LAN - -This section of testing was perform in a 10Mbps LAN with mixed 10Base2 and -10BaseT interfaces. The LAN was interconnected with a D-Link HUB, and a -connection to the Internet was secured through an Efficient Networks -SpeedStream router. The address of the router is 216.36.95.129. - - -13. Connect to LAN - - Connect both the LOCAL and REMOTE ethernet cards to the non-isolated LAN. - Verify that the "100" LED is off, and the "FD" LED is off. - LOCAL: more lnkfail - Verify that the result printed is 0. - LOCAL: more afduplx - Verify that the result printed is 0. - LOCAL: more aspeed - Verify that the result printed is 10. - Perform Test #2 (Ping Remote Side) to verify connection. - - Test Results: Passed - - -14. Test Promiscuous Mode - - LOCAL: /usr/sbin/tcpdump -p -i eth0 host 216.36.95.129 - REMOTE: ping -c5 216.36.95.129 - Verify that the LOCAL "tcpdump" program sees the pings to 216.36.95.129. - - Test Results: Passed - -15. Test Multicast Mode - - The "route" command must be executed as root. - LOCAL: route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 - REMOTE: route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 - LOCAL: /usr/sbin/tcpdump -p -i eth0 host 216.36.95.129 - REMOTE: ping 224.0.0.1 - Verify that the REMOTE machine gets at least one ICMP response from - 216.36.95.135. You will probably also see ICMP responses from other - Linux machines listening on the LAN. - Also, by inspecting the output of the LOCAL "tcpdump" you can see which - packets are Broadcast (B), Multicast (M), or Point-to-point (P). - - Test Results: Passed - -16. Test LED Control - - LOCAL: echo 6 > leda - LOCAL: echo 7 > ledb - LOCAL: more leda - Verify that the result printed is 6. - LOCAL: more ledb - Verify that the result printed is 7. - Perform Test #2 (Ping Remote Side) to verify connection. - Verify that the two LEDs toggle when packets are received and transmitted. - - Test Results: Passed - - - -How to obtain the latest version: -================================= - - http://www.smsc.com - - -Known bugs: -=========== - - 1. You cannot yet set the hardware address. - - 2. Hardware multicast filtering is not yet supported. - - 3. The driver does not support multiple cards in a system (yet) - - 4. One anomoly was observed during testing with an Athlon Thunderbird 1GHz system - during FTP uploads to a Pentim 4 1.3GHz system running Windows 2000 Adv Server, - where FTP transfer speed were observed to be 40-50% below normal. The cause - of the anomoly is unknown. - - -Contacting me: -============== - Pramod Bhardwaj, pramod.bhardwaj@smsc.com - _