diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/net/ethernet/dlink | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/net/ethernet/dlink')
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/Kconfig | 86 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/Makefile | 8 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.c | 529 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.h | 168 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.c | 987 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.h | 117 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.c | 1787 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.h | 441 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/net/ethernet/dlink/sundance.c | 1939 |
9 files changed, 0 insertions, 6062 deletions
diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/Kconfig b/ANDROID_3.4.5/drivers/net/ethernet/dlink/Kconfig deleted file mode 100644 index b5afe218..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/Kconfig +++ /dev/null @@ -1,86 +0,0 @@ -# -# D-Link device configuration -# - -config NET_VENDOR_DLINK - bool "D-Link devices" - default y - depends on PCI || PARPORT - ---help--- - If you have a network (Ethernet) card belonging to this class, say Y - and read the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about D-Link devices. If you say Y, you will be asked for - your specific card in the following questions. - -if NET_VENDOR_DLINK - -config DE600 - tristate "D-Link DE600 pocket adapter support" - depends on PARPORT - ---help--- - This is a network (Ethernet) device which attaches to your parallel - port. Read <file:Documentation/networking/DLINK.txt> as well as the - Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>, if you want to use - this. It is possible to have several devices share a single parallel - port and it is safe to compile the corresponding drivers into the - kernel. - - To compile this driver as a module, choose M here: the module - will be called de600. - -config DE620 - tristate "D-Link DE620 pocket adapter support" - depends on PARPORT - ---help--- - This is a network (Ethernet) device which attaches to your parallel - port. Read <file:Documentation/networking/DLINK.txt> as well as the - Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>, if you want to use - this. It is possible to have several devices share a single parallel - port and it is safe to compile the corresponding drivers into the - kernel. - - To compile this driver as a module, choose M here: the module - will be called de620. - -config DL2K - tristate "DL2000/TC902x-based Gigabit Ethernet support" - depends on PCI - select CRC32 - ---help--- - This driver supports DL2000/TC902x-based Gigabit ethernet cards, - which includes - D-Link DGE-550T Gigabit Ethernet Adapter. - D-Link DL2000-based Gigabit Ethernet Adapter. - Sundance/Tamarack TC902x Gigabit Ethernet Adapter. - - To compile this driver as a module, choose M here: the - module will be called dl2k. - -config SUNDANCE - tristate "Sundance Alta support" - depends on PCI - select CRC32 - select NET_CORE - select MII - ---help--- - This driver is for the Sundance "Alta" chip. - More specific information and updates are available from - <http://www.scyld.com/network/sundance.html>. - -config SUNDANCE_MMIO - bool "Use MMIO instead of PIO" - depends on SUNDANCE - ---help--- - Enable memory-mapped I/O for interaction with Sundance NIC registers. - Do NOT enable this by default, PIO (enabled when MMIO is disabled) - is known to solve bugs on certain chips. - - If unsure, say N. - -endif # NET_VENDOR_DLINK diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/Makefile b/ANDROID_3.4.5/drivers/net/ethernet/dlink/Makefile deleted file mode 100644 index c705eaa4..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the D-Link network device drivers. -# - -obj-$(CONFIG_DE600) += de600.o -obj-$(CONFIG_DE620) += de620.o -obj-$(CONFIG_DL2K) += dl2k.o -obj-$(CONFIG_SUNDANCE) += sundance.o diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.c b/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.c deleted file mode 100644 index 414f0eea..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.c +++ /dev/null @@ -1,529 +0,0 @@ -static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj0rn@blox.se)\n"; -/* - * de600.c - * - * Linux driver for the D-Link DE-600 Ethernet pocket adapter. - * - * Portions (C) Copyright 1993, 1994 by Bjorn Ekwall - * The Author may be reached as bj0rn@blox.se - * - * Based on adapter information gathered from DE600.ASM by D-Link Inc., - * as included on disk C in the v.2.11 of PC/TCP from FTP Software. - * For DE600.asm: - * Portions (C) Copyright 1990 D-Link, Inc. - * Copyright, 1988-1992, Russell Nelson, Crynwr Software - * - * Adapted to the sample network driver core for linux, - * written by: Donald Becker <becker@super.org> - * (Now at <becker@scyld.com>) - * - **************************************************************/ -/* - * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - **************************************************************/ - -/* Add more time here if your adapter won't work OK: */ -#define DE600_SLOW_DOWN udelay(delay_time) - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/io.h> - -#include "de600.h" - -static bool check_lost = true; -module_param(check_lost, bool, 0); -MODULE_PARM_DESC(check_lost, "If set then check for unplugged de600"); - -static unsigned int delay_time = 10; -module_param(delay_time, int, 0); -MODULE_PARM_DESC(delay_time, "DE-600 deley on I/O in microseconds"); - - -/* - * D-Link driver variables: - */ - -static volatile int rx_page; - -#define TX_PAGES 2 -static volatile int tx_fifo[TX_PAGES]; -static volatile int tx_fifo_in; -static volatile int tx_fifo_out; -static volatile int free_tx_pages = TX_PAGES; -static int was_down; -static DEFINE_SPINLOCK(de600_lock); - -static inline u8 de600_read_status(struct net_device *dev) -{ - u8 status; - - outb_p(STATUS, DATA_PORT); - status = inb(STATUS_PORT); - outb_p(NULL_COMMAND | HI_NIBBLE, DATA_PORT); - - return status; -} - -static inline u8 de600_read_byte(unsigned char type, struct net_device *dev) -{ - /* dev used by macros */ - u8 lo; - outb_p((type), DATA_PORT); - lo = ((unsigned char)inb(STATUS_PORT)) >> 4; - outb_p((type) | HI_NIBBLE, DATA_PORT); - return ((unsigned char)inb(STATUS_PORT) & (unsigned char)0xf0) | lo; -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * after booting when 'ifconfig <dev->name> $IP_ADDR' is run (in rc.inet1). - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is a non-reboot way to recover if something goes wrong. - */ - -static int de600_open(struct net_device *dev) -{ - unsigned long flags; - int ret = request_irq(DE600_IRQ, de600_interrupt, 0, dev->name, dev); - if (ret) { - printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, DE600_IRQ); - return ret; - } - spin_lock_irqsave(&de600_lock, flags); - ret = adapter_init(dev); - spin_unlock_irqrestore(&de600_lock, flags); - return ret; -} - -/* - * The inverse routine to de600_open(). - */ - -static int de600_close(struct net_device *dev) -{ - select_nic(); - rx_page = 0; - de600_put_command(RESET); - de600_put_command(STOP_RESET); - de600_put_command(0); - select_prn(); - free_irq(DE600_IRQ, dev); - return 0; -} - -static inline void trigger_interrupt(struct net_device *dev) -{ - de600_put_command(FLIP_IRQ); - select_prn(); - DE600_SLOW_DOWN; - select_nic(); - de600_put_command(0); -} - -/* - * Copy a buffer to the adapter transmit page memory. - * Start sending. - */ - -static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned long flags; - int transmit_from; - int len; - int tickssofar; - u8 *buffer = skb->data; - int i; - - if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ - tickssofar = jiffies - dev_trans_start(dev); - if (tickssofar < HZ/20) - return NETDEV_TX_BUSY; - /* else */ - printk(KERN_WARNING "%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem"); - /* Restart the adapter. */ - spin_lock_irqsave(&de600_lock, flags); - if (adapter_init(dev)) { - spin_unlock_irqrestore(&de600_lock, flags); - return NETDEV_TX_BUSY; - } - spin_unlock_irqrestore(&de600_lock, flags); - } - - /* Start real output */ - pr_debug("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages); - - if ((len = skb->len) < RUNT) - len = RUNT; - - spin_lock_irqsave(&de600_lock, flags); - select_nic(); - tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; - tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */ - - if(check_lost) - { - /* This costs about 40 instructions per packet... */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - de600_read_byte(READ_DATA, dev); - if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) { - if (adapter_init(dev)) { - spin_unlock_irqrestore(&de600_lock, flags); - return NETDEV_TX_BUSY; - } - } - } - - de600_setup_address(transmit_from, RW_ADDR); - for (i = 0; i < skb->len ; ++i, ++buffer) - de600_put_byte(*buffer); - for (; i < len; ++i) - de600_put_byte(0); - - if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ - dev->trans_start = jiffies; - netif_start_queue(dev); /* allow more packets into adapter */ - /* Send page and generate a faked interrupt */ - de600_setup_address(transmit_from, TX_ADDR); - de600_put_command(TX_ENABLE); - } - else { - if (free_tx_pages) - netif_start_queue(dev); - else - netif_stop_queue(dev); - select_prn(); - } - spin_unlock_irqrestore(&de600_lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* - * The typical workload of the driver: - * Handle the network interface interrupts. - */ - -static irqreturn_t de600_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - u8 irq_status; - int retrig = 0; - int boguscount = 0; - - spin_lock(&de600_lock); - - select_nic(); - irq_status = de600_read_status(dev); - - do { - pr_debug("de600_interrupt (%02X)\n", irq_status); - - if (irq_status & RX_GOOD) - de600_rx_intr(dev); - else if (!(irq_status & RX_BUSY)) - de600_put_command(RX_ENABLE); - - /* Any transmission in progress? */ - if (free_tx_pages < TX_PAGES) - retrig = de600_tx_intr(dev, irq_status); - else - retrig = 0; - - irq_status = de600_read_status(dev); - } while ( (irq_status & RX_GOOD) || ((++boguscount < 100) && retrig) ); - /* - * Yeah, it _looks_ like busy waiting, smells like busy waiting - * and I know it's not PC, but please, it will only occur once - * in a while and then only for a loop or so (< 1ms for sure!) - */ - - /* Enable adapter interrupts */ - select_prn(); - if (retrig) - trigger_interrupt(dev); - spin_unlock(&de600_lock); - return IRQ_HANDLED; -} - -static int de600_tx_intr(struct net_device *dev, int irq_status) -{ - /* - * Returns 1 if tx still not done - */ - - /* Check if current transmission is done yet */ - if (irq_status & TX_BUSY) - return 1; /* tx not done, try again */ - - /* else */ - /* If last transmission OK then bump fifo index */ - if (!(irq_status & TX_FAILED16)) { - tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES; - ++free_tx_pages; - dev->stats.tx_packets++; - netif_wake_queue(dev); - } - - /* More to send, or resend last packet? */ - if ((free_tx_pages < TX_PAGES) || (irq_status & TX_FAILED16)) { - dev->trans_start = jiffies; - de600_setup_address(tx_fifo[tx_fifo_out], TX_ADDR); - de600_put_command(TX_ENABLE); - return 1; - } - /* else */ - - return 0; -} - -/* - * We have a good packet, get it out of the adapter. - */ -static void de600_rx_intr(struct net_device *dev) -{ - struct sk_buff *skb; - int i; - int read_from; - int size; - unsigned char *buffer; - - /* Get size of received packet */ - size = de600_read_byte(RX_LEN, dev); /* low byte */ - size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */ - size -= 4; /* Ignore trailing 4 CRC-bytes */ - - /* Tell adapter where to store next incoming packet, enable receiver */ - read_from = rx_page_adr(); - next_rx_page(); - de600_put_command(RX_ENABLE); - - if ((size < 32) || (size > 1535)) { - printk(KERN_WARNING "%s: Bogus packet size %d.\n", dev->name, size); - if (size > 10000) - adapter_init(dev); - return; - } - - skb = netdev_alloc_skb(dev, size + 2); - if (skb == NULL) { - printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size); - return; - } - /* else */ - - skb_reserve(skb,2); /* Align */ - - /* 'skb->data' points to the start of sk_buff data area. */ - buffer = skb_put(skb,size); - - /* copy the packet into the buffer */ - de600_setup_address(read_from, RW_ADDR); - for (i = size; i > 0; --i, ++buffer) - *buffer = de600_read_byte(READ_DATA, dev); - - skb->protocol=eth_type_trans(skb,dev); - - netif_rx(skb); - - /* update stats */ - dev->stats.rx_packets++; /* count all receives */ - dev->stats.rx_bytes += size; /* count all received bytes */ - - /* - * If any worth-while packets have been received, netif_rx() - * will work on them when we get to the tasklets. - */ -} - -static const struct net_device_ops de600_netdev_ops = { - .ndo_open = de600_open, - .ndo_stop = de600_close, - .ndo_start_xmit = de600_start_xmit, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - - -static struct net_device * __init de600_probe(void) -{ - int i; - struct net_device *dev; - int err; - - dev = alloc_etherdev(0); - if (!dev) - return ERR_PTR(-ENOMEM); - - - if (!request_region(DE600_IO, 3, "de600")) { - printk(KERN_WARNING "DE600: port 0x%x busy\n", DE600_IO); - err = -EBUSY; - goto out; - } - - printk(KERN_INFO "%s: D-Link DE-600 pocket adapter", dev->name); - /* Alpha testers must have the version number to report bugs. */ - pr_debug("%s", version); - - /* probe for adapter */ - err = -ENODEV; - rx_page = 0; - select_nic(); - (void)de600_read_status(dev); - de600_put_command(RESET); - de600_put_command(STOP_RESET); - if (de600_read_status(dev) & 0xf0) { - printk(": not at I/O %#3x.\n", DATA_PORT); - goto out1; - } - - /* - * Maybe we found one, - * have to check if it is a D-Link DE-600 adapter... - */ - - /* Get the adapter ethernet address from the ROM */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - for (i = 0; i < ETH_ALEN; i++) { - dev->dev_addr[i] = de600_read_byte(READ_DATA, dev); - dev->broadcast[i] = 0xff; - } - - /* Check magic code */ - if ((dev->dev_addr[1] == 0xde) && (dev->dev_addr[2] == 0x15)) { - /* OK, install real address */ - dev->dev_addr[0] = 0x00; - dev->dev_addr[1] = 0x80; - dev->dev_addr[2] = 0xc8; - dev->dev_addr[3] &= 0x0f; - dev->dev_addr[3] |= 0x70; - } else { - printk(" not identified in the printer port\n"); - goto out1; - } - - printk(", Ethernet Address: %pM\n", dev->dev_addr); - - dev->netdev_ops = &de600_netdev_ops; - - dev->flags&=~IFF_MULTICAST; - - select_prn(); - - err = register_netdev(dev); - if (err) - goto out1; - - return dev; - -out1: - release_region(DE600_IO, 3); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -static int adapter_init(struct net_device *dev) -{ - int i; - - select_nic(); - rx_page = 0; /* used by RESET */ - de600_put_command(RESET); - de600_put_command(STOP_RESET); - - /* Check if it is still there... */ - /* Get the some bytes of the adapter ethernet address from the ROM */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - de600_read_byte(READ_DATA, dev); - if ((de600_read_byte(READ_DATA, dev) != 0xde) || - (de600_read_byte(READ_DATA, dev) != 0x15)) { - /* was: if (de600_read_status(dev) & 0xf0) { */ - printk("Something has happened to the DE-600! Please check it and do a new ifconfig!\n"); - /* Goodbye, cruel world... */ - dev->flags &= ~IFF_UP; - de600_close(dev); - was_down = 1; - netif_stop_queue(dev); /* Transmit busy... */ - return 1; /* failed */ - } - - if (was_down) { - printk(KERN_INFO "%s: Thanks, I feel much better now!\n", dev->name); - was_down = 0; - } - - tx_fifo_in = 0; - tx_fifo_out = 0; - free_tx_pages = TX_PAGES; - - - /* set the ether address. */ - de600_setup_address(NODE_ADDRESS, RW_ADDR); - for (i = 0; i < ETH_ALEN; i++) - de600_put_byte(dev->dev_addr[i]); - - /* where to start saving incoming packets */ - rx_page = RX_BP | RX_BASE_PAGE; - de600_setup_address(MEM_4K, RW_ADDR); - /* Enable receiver */ - de600_put_command(RX_ENABLE); - select_prn(); - - netif_start_queue(dev); - - return 0; /* OK */ -} - -static struct net_device *de600_dev; - -static int __init de600_init(void) -{ - de600_dev = de600_probe(); - if (IS_ERR(de600_dev)) - return PTR_ERR(de600_dev); - return 0; -} - -static void __exit de600_exit(void) -{ - unregister_netdev(de600_dev); - release_region(DE600_IO, 3); - free_netdev(de600_dev); -} - -module_init(de600_init); -module_exit(de600_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.h b/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.h deleted file mode 100644 index e80ecbab..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de600.h +++ /dev/null @@ -1,168 +0,0 @@ -/************************************************** - * * - * Definition of D-Link Ethernet Pocket adapter * - * * - **************************************************/ -/* - * D-Link Ethernet pocket adapter ports - */ -/* - * OK, so I'm cheating, but there are an awful lot of - * reads and writes in order to get anything in and out - * of the DE-600 with 4 bits at a time in the parallel port, - * so every saved instruction really helps :-) - */ - -#ifndef DE600_IO -#define DE600_IO 0x378 -#endif - -#define DATA_PORT (DE600_IO) -#define STATUS_PORT (DE600_IO + 1) -#define COMMAND_PORT (DE600_IO + 2) - -#ifndef DE600_IRQ -#define DE600_IRQ 7 -#endif -/* - * It really should look like this, and autoprobing as well... - * -#define DATA_PORT (dev->base_addr + 0) -#define STATUS_PORT (dev->base_addr + 1) -#define COMMAND_PORT (dev->base_addr + 2) -#define DE600_IRQ dev->irq - */ - -/* - * D-Link COMMAND_PORT commands - */ -#define SELECT_NIC 0x04 /* select Network Interface Card */ -#define SELECT_PRN 0x1c /* select Printer */ -#define NML_PRN 0xec /* normal Printer situation */ -#define IRQEN 0x10 /* enable IRQ line */ - -/* - * D-Link STATUS_PORT - */ -#define RX_BUSY 0x80 -#define RX_GOOD 0x40 -#define TX_FAILED16 0x10 -#define TX_BUSY 0x08 - -/* - * D-Link DATA_PORT commands - * command in low 4 bits - * data in high 4 bits - * select current data nibble with HI_NIBBLE bit - */ -#define WRITE_DATA 0x00 /* write memory */ -#define READ_DATA 0x01 /* read memory */ -#define STATUS 0x02 /* read status register */ -#define COMMAND 0x03 /* write command register (see COMMAND below) */ -#define NULL_COMMAND 0x04 /* null command */ -#define RX_LEN 0x05 /* read received packet length */ -#define TX_ADDR 0x06 /* set adapter transmit memory address */ -#define RW_ADDR 0x07 /* set adapter read/write memory address */ -#define HI_NIBBLE 0x08 /* read/write the high nibble of data, - or-ed with rest of command */ - -/* - * command register, accessed through DATA_PORT with low bits = COMMAND - */ -#define RX_ALL 0x01 /* PROMISCUOUS */ -#define RX_BP 0x02 /* default: BROADCAST & PHYSICAL ADDRESS */ -#define RX_MBP 0x03 /* MULTICAST, BROADCAST & PHYSICAL ADDRESS */ - -#define TX_ENABLE 0x04 /* bit 2 */ -#define RX_ENABLE 0x08 /* bit 3 */ - -#define RESET 0x80 /* set bit 7 high */ -#define STOP_RESET 0x00 /* set bit 7 low */ - -/* - * data to command register - * (high 4 bits in write to DATA_PORT) - */ -#define RX_PAGE2_SELECT 0x10 /* bit 4, only 2 pages to select */ -#define RX_BASE_PAGE 0x20 /* bit 5, always set when specifying RX_ADDR */ -#define FLIP_IRQ 0x40 /* bit 6 */ - -/* - * D-Link adapter internal memory: - * - * 0-2K 1:st transmit page (send from pointer up to 2K) - * 2-4K 2:nd transmit page (send from pointer up to 4K) - * - * 4-6K 1:st receive page (data from 4K upwards) - * 6-8K 2:nd receive page (data from 6K upwards) - * - * 8K+ Adapter ROM (contains magic code and last 3 bytes of Ethernet address) - */ -#define MEM_2K 0x0800 /* 2048 */ -#define MEM_4K 0x1000 /* 4096 */ -#define MEM_6K 0x1800 /* 6144 */ -#define NODE_ADDRESS 0x2000 /* 8192 */ - -#define RUNT 60 /* Too small Ethernet packet */ - -/************************************************** - * * - * End of definition * - * * - **************************************************/ - -/* - * Index to functions, as function prototypes. - */ -/* Routines used internally. (See "convenience macros") */ -static u8 de600_read_status(struct net_device *dev); -static u8 de600_read_byte(unsigned char type, struct net_device *dev); - -/* Put in the device structure. */ -static int de600_open(struct net_device *dev); -static int de600_close(struct net_device *dev); -static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev); - -/* Dispatch from interrupts. */ -static irqreturn_t de600_interrupt(int irq, void *dev_id); -static int de600_tx_intr(struct net_device *dev, int irq_status); -static void de600_rx_intr(struct net_device *dev); - -/* Initialization */ -static void trigger_interrupt(struct net_device *dev); -static int adapter_init(struct net_device *dev); - -/* - * Convenience macros/functions for D-Link adapter - */ - -#define select_prn() outb_p(SELECT_PRN, COMMAND_PORT); DE600_SLOW_DOWN -#define select_nic() outb_p(SELECT_NIC, COMMAND_PORT); DE600_SLOW_DOWN - -/* Thanks for hints from Mark Burton <markb@ordern.demon.co.uk> */ -#define de600_put_byte(data) ( \ - outb_p(((data) << 4) | WRITE_DATA , DATA_PORT), \ - outb_p(((data) & 0xf0) | WRITE_DATA | HI_NIBBLE, DATA_PORT)) - -/* - * The first two outb_p()'s below could perhaps be deleted if there - * would be more delay in the last two. Not certain about it yet... - */ -#define de600_put_command(cmd) ( \ - outb_p(( rx_page << 4) | COMMAND , DATA_PORT), \ - outb_p(( rx_page & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT), \ - outb_p(((rx_page | cmd) << 4) | COMMAND , DATA_PORT), \ - outb_p(((rx_page | cmd) & 0xf0) | COMMAND | HI_NIBBLE, DATA_PORT)) - -#define de600_setup_address(addr,type) ( \ - outb_p((((addr) << 4) & 0xf0) | type , DATA_PORT), \ - outb_p(( (addr) & 0xf0) | type | HI_NIBBLE, DATA_PORT), \ - outb_p((((addr) >> 4) & 0xf0) | type , DATA_PORT), \ - outb_p((((addr) >> 8) & 0xf0) | type | HI_NIBBLE, DATA_PORT)) - -#define rx_page_adr() ((rx_page & RX_PAGE2_SELECT)?(MEM_6K):(MEM_4K)) - -/* Flip bit, only 2 pages */ -#define next_rx_page() (rx_page ^= RX_PAGE2_SELECT) - -#define tx_page_adr(a) (((a) + 1) * MEM_2K) diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.c b/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.c deleted file mode 100644 index 2e2bc60e..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.c +++ /dev/null @@ -1,987 +0,0 @@ -/* - * de620.c $Revision: 1.40 $ BETA - * - * - * Linux driver for the D-Link DE-620 Ethernet pocket adapter. - * - * Portions (C) Copyright 1993, 1994 by Bjorn Ekwall <bj0rn@blox.se> - * - * Based on adapter information gathered from DOS packetdriver - * sources from D-Link Inc: (Special thanks to Henry Ngai of D-Link.) - * Portions (C) Copyright D-Link SYSTEM Inc. 1991, 1992 - * Copyright, 1988, Russell Nelson, Crynwr Software - * - * Adapted to the sample network driver core for linux, - * written by: Donald Becker <becker@super.org> - * (Now at <becker@scyld.com>) - * - * Valuable assistance from: - * J. Joshua Kopper <kopper@rtsg.mot.com> - * Olav Kvittem <Olav.Kvittem@uninett.no> - * Germano Caronni <caronni@nessie.cs.id.ethz.ch> - * Jeremy Fitzhardinge <jeremy@suite.sw.oz.au> - * - *****************************************************************************/ -/* - * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - *****************************************************************************/ -static const char version[] = - "de620.c: $Revision: 1.40 $, Bjorn Ekwall <bj0rn@blox.se>\n"; - -/*********************************************************************** - * - * "Tuning" section. - * - * Compile-time options: (see below for descriptions) - * -DDE620_IO=0x378 (lpt1) - * -DDE620_IRQ=7 (lpt1) - * -DSHUTDOWN_WHEN_LOST - * -DCOUNT_LOOPS - * -DLOWSPEED - * -DREAD_DELAY - * -DWRITE_DELAY - */ - -/* - * This driver assumes that the printer port is a "normal", - * dumb, uni-directional port! - * If your port is "fancy" in any way, please try to set it to "normal" - * with your BIOS setup. I have no access to machines with bi-directional - * ports, so I can't test such a driver :-( - * (Yes, I _know_ it is possible to use DE620 with bidirectional ports...) - * - * There are some clones of DE620 out there, with different names. - * If the current driver does not recognize a clone, try to change - * the following #define to: - * - * #define DE620_CLONE 1 - */ -#define DE620_CLONE 0 - -/* - * If the adapter has problems with high speeds, enable this #define - * otherwise full printerport speed will be attempted. - * - * You can tune the READ_DELAY/WRITE_DELAY below if you enable LOWSPEED - * -#define LOWSPEED - */ - -#ifndef READ_DELAY -#define READ_DELAY 100 /* adapter internal read delay in 100ns units */ -#endif - -#ifndef WRITE_DELAY -#define WRITE_DELAY 100 /* adapter internal write delay in 100ns units */ -#endif - -/* - * Enable this #define if you want the adapter to do a "ifconfig down" on - * itself when we have detected that something is possibly wrong with it. - * The default behaviour is to retry with "adapter_init()" until success. - * This should be used for debugging purposes only. - * -#define SHUTDOWN_WHEN_LOST - */ - -#ifdef LOWSPEED -/* - * Enable this #define if you want to see debugging output that show how long - * we have to wait before the DE-620 is ready for the next read/write/command. - * -#define COUNT_LOOPS - */ -#endif - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/inet.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> - -#include <asm/io.h> - -/* Constant definitions for the DE-620 registers, commands and bits */ -#include "de620.h" - -typedef unsigned char byte; - -/******************************************************* - * * - * Definition of D-Link DE-620 Ethernet Pocket adapter * - * See also "de620.h" * - * * - *******************************************************/ -#ifndef DE620_IO /* Compile-time configurable */ -#define DE620_IO 0x378 -#endif - -#ifndef DE620_IRQ /* Compile-time configurable */ -#define DE620_IRQ 7 -#endif - -#define DATA_PORT (dev->base_addr) -#define STATUS_PORT (dev->base_addr + 1) -#define COMMAND_PORT (dev->base_addr + 2) - -#define RUNT 60 /* Too small Ethernet packet */ -#define GIANT 1514 /* largest legal size packet, no fcs */ - -/* - * Force media with insmod: - * insmod de620.o bnc=1 - * or - * insmod de620.o utp=1 - * - * Force io and/or irq with insmod: - * insmod de620.o io=0x378 irq=7 - * - * Make a clone skip the Ethernet-address range check: - * insmod de620.o clone=1 - */ -static int bnc; -static int utp; -static int io = DE620_IO; -static int irq = DE620_IRQ; -static int clone = DE620_CLONE; - -static spinlock_t de620_lock; - -module_param(bnc, int, 0); -module_param(utp, int, 0); -module_param(io, int, 0); -module_param(irq, int, 0); -module_param(clone, int, 0); -MODULE_PARM_DESC(bnc, "DE-620 set BNC medium (0-1)"); -MODULE_PARM_DESC(utp, "DE-620 set UTP medium (0-1)"); -MODULE_PARM_DESC(io, "DE-620 I/O base address,required"); -MODULE_PARM_DESC(irq, "DE-620 IRQ number,required"); -MODULE_PARM_DESC(clone, "Check also for non-D-Link DE-620 clones (0-1)"); - -/*********************************************** - * * - * Index to functions, as function prototypes. * - * * - ***********************************************/ - -/* - * Routines used internally. (See also "convenience macros.. below") - */ - -/* Put in the device structure. */ -static int de620_open(struct net_device *); -static int de620_close(struct net_device *); -static void de620_set_multicast_list(struct net_device *); -static int de620_start_xmit(struct sk_buff *, struct net_device *); - -/* Dispatch from interrupts. */ -static irqreturn_t de620_interrupt(int, void *); -static int de620_rx_intr(struct net_device *); - -/* Initialization */ -static int adapter_init(struct net_device *); -static int read_eeprom(struct net_device *); - - -/* - * D-Link driver variables: - */ -#define SCR_DEF NIBBLEMODE |INTON | SLEEP | AUTOTX -#define TCR_DEF RXPB /* not used: | TXSUCINT | T16INT */ -#define DE620_RX_START_PAGE 12 /* 12 pages (=3k) reserved for tx */ -#define DEF_NIC_CMD IRQEN | ICEN | DS1 - -static volatile byte NIC_Cmd; -static volatile byte next_rx_page; -static byte first_rx_page; -static byte last_rx_page; -static byte EIPRegister; - -static struct nic { - byte NodeID[6]; - byte RAM_Size; - byte Model; - byte Media; - byte SCR; -} nic_data; - -/********************************************************** - * * - * Convenience macros/functions for D-Link DE-620 adapter * - * * - **********************************************************/ -#define de620_tx_buffs(dd) (inb(STATUS_PORT) & (TXBF0 | TXBF1)) -#define de620_flip_ds(dd) NIC_Cmd ^= DS0 | DS1; outb(NIC_Cmd, COMMAND_PORT); - -/* Check for ready-status, and return a nibble (high 4 bits) for data input */ -#ifdef COUNT_LOOPS -static int tot_cnt; -#endif -static inline byte -de620_ready(struct net_device *dev) -{ - byte value; - register short int cnt = 0; - - while ((((value = inb(STATUS_PORT)) & READY) == 0) && (cnt <= 1000)) - ++cnt; - -#ifdef COUNT_LOOPS - tot_cnt += cnt; -#endif - return value & 0xf0; /* nibble */ -} - -static inline void -de620_send_command(struct net_device *dev, byte cmd) -{ - de620_ready(dev); - if (cmd == W_DUMMY) - outb(NIC_Cmd, COMMAND_PORT); - - outb(cmd, DATA_PORT); - - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - de620_ready(dev); - outb(NIC_Cmd, COMMAND_PORT); -} - -static inline void -de620_put_byte(struct net_device *dev, byte value) -{ - /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ - de620_ready(dev); - outb(value, DATA_PORT); - de620_flip_ds(dev); -} - -static inline byte -de620_read_byte(struct net_device *dev) -{ - byte value; - - /* The de620_ready() makes 7 loops, on the average, on a DX2/66 */ - value = de620_ready(dev); /* High nibble */ - de620_flip_ds(dev); - value |= de620_ready(dev) >> 4; /* Low nibble */ - return value; -} - -static inline void -de620_write_block(struct net_device *dev, byte *buffer, int count, int pad) -{ -#ifndef LOWSPEED - byte uflip = NIC_Cmd ^ (DS0 | DS1); - byte dflip = NIC_Cmd; -#else /* LOWSPEED */ -#ifdef COUNT_LOOPS - int bytes = count; -#endif /* COUNT_LOOPS */ -#endif /* LOWSPEED */ - -#ifdef LOWSPEED -#ifdef COUNT_LOOPS - tot_cnt = 0; -#endif /* COUNT_LOOPS */ - /* No further optimization useful, the limit is in the adapter. */ - for ( ; count > 0; --count, ++buffer) { - de620_put_byte(dev,*buffer); - } - for ( count = pad ; count > 0; --count, ++buffer) { - de620_put_byte(dev, 0); - } - de620_send_command(dev,W_DUMMY); -#ifdef COUNT_LOOPS - /* trial debug output: loops per byte in de620_ready() */ - printk("WRITE(%d)\n", tot_cnt/((bytes?bytes:1))); -#endif /* COUNT_LOOPS */ -#else /* not LOWSPEED */ - for ( ; count > 0; count -=2) { - outb(*buffer++, DATA_PORT); - outb(uflip, COMMAND_PORT); - outb(*buffer++, DATA_PORT); - outb(dflip, COMMAND_PORT); - } - de620_send_command(dev,W_DUMMY); -#endif /* LOWSPEED */ -} - -static inline void -de620_read_block(struct net_device *dev, byte *data, int count) -{ -#ifndef LOWSPEED - byte value; - byte uflip = NIC_Cmd ^ (DS0 | DS1); - byte dflip = NIC_Cmd; -#else /* LOWSPEED */ -#ifdef COUNT_LOOPS - int bytes = count; - - tot_cnt = 0; -#endif /* COUNT_LOOPS */ -#endif /* LOWSPEED */ - -#ifdef LOWSPEED - /* No further optimization useful, the limit is in the adapter. */ - while (count-- > 0) { - *data++ = de620_read_byte(dev); - de620_flip_ds(dev); - } -#ifdef COUNT_LOOPS - /* trial debug output: loops per byte in de620_ready() */ - printk("READ(%d)\n", tot_cnt/(2*(bytes?bytes:1))); -#endif /* COUNT_LOOPS */ -#else /* not LOWSPEED */ - while (count-- > 0) { - value = inb(STATUS_PORT) & 0xf0; /* High nibble */ - outb(uflip, COMMAND_PORT); - *data++ = value | inb(STATUS_PORT) >> 4; /* Low nibble */ - outb(dflip , COMMAND_PORT); - } -#endif /* LOWSPEED */ -} - -static inline void -de620_set_delay(struct net_device *dev) -{ - de620_ready(dev); - outb(W_DFR, DATA_PORT); - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - - de620_ready(dev); -#ifdef LOWSPEED - outb(WRITE_DELAY, DATA_PORT); -#else - outb(0, DATA_PORT); -#endif - de620_flip_ds(dev); - - de620_ready(dev); -#ifdef LOWSPEED - outb(READ_DELAY, DATA_PORT); -#else - outb(0, DATA_PORT); -#endif - de620_flip_ds(dev); -} - -static inline void -de620_set_register(struct net_device *dev, byte reg, byte value) -{ - de620_ready(dev); - outb(reg, DATA_PORT); - outb(NIC_Cmd ^ CS0, COMMAND_PORT); - - de620_put_byte(dev, value); -} - -static inline byte -de620_get_register(struct net_device *dev, byte reg) -{ - byte value; - - de620_send_command(dev,reg); - value = de620_read_byte(dev); - de620_send_command(dev,W_DUMMY); - - return value; -} - -/********************************************************************* - * - * Open/initialize the board. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is a non-reboot way to recover if something goes wrong. - * - */ -static int de620_open(struct net_device *dev) -{ - int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev); - if (ret) { - printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq); - return ret; - } - - if (adapter_init(dev)) { - ret = -EIO; - goto out_free_irq; - } - - netif_start_queue(dev); - return 0; - -out_free_irq: - free_irq(dev->irq, dev); - return ret; -} - -/************************************************ - * - * The inverse routine to de620_open(). - * - */ - -static int de620_close(struct net_device *dev) -{ - netif_stop_queue(dev); - /* disable recv */ - de620_set_register(dev, W_TCR, RXOFF); - free_irq(dev->irq, dev); - return 0; -} - -/********************************************* - * - * Set or clear the multicast filter for this adaptor. - * (no real multicast implemented for the DE-620, but she can be promiscuous...) - * - */ - -static void de620_set_multicast_list(struct net_device *dev) -{ - if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { /* Enable promiscuous mode */ - de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL); - } - else - { /* Disable promiscuous mode, use normal mode */ - de620_set_register(dev, W_TCR, TCR_DEF); - } -} - -/******************************************************* - * - * Handle timeouts on transmit - */ - -static void de620_timeout(struct net_device *dev) -{ - printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); - /* Restart the adapter. */ - if (!adapter_init(dev)) /* maybe close it */ - netif_wake_queue(dev); -} - -/******************************************************* - * - * Copy a buffer to the adapter transmit page memory. - * Start sending. - */ -static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned long flags; - int len; - byte *buffer = skb->data; - byte using_txbuf; - - using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */ - - netif_stop_queue(dev); - - - if ((len = skb->len) < RUNT) - len = RUNT; - if (len & 1) /* send an even number of bytes */ - ++len; - - /* Start real output */ - - spin_lock_irqsave(&de620_lock, flags); - pr_debug("de620_start_xmit: len=%d, bufs 0x%02x\n", - (int)skb->len, using_txbuf); - - /* select a free tx buffer. if there is one... */ - switch (using_txbuf) { - default: /* both are free: use TXBF0 */ - case TXBF1: /* use TXBF0 */ - de620_send_command(dev,W_CR | RW0); - using_txbuf |= TXBF0; - break; - - case TXBF0: /* use TXBF1 */ - de620_send_command(dev,W_CR | RW1); - using_txbuf |= TXBF1; - break; - - case (TXBF0 | TXBF1): /* NONE!!! */ - printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name); - spin_unlock_irqrestore(&de620_lock, flags); - return NETDEV_TX_BUSY; - } - de620_write_block(dev, buffer, skb->len, len-skb->len); - - if(!(using_txbuf == (TXBF0 | TXBF1))) - netif_wake_queue(dev); - - dev->stats.tx_packets++; - spin_unlock_irqrestore(&de620_lock, flags); - dev_kfree_skb (skb); - return NETDEV_TX_OK; -} - -/***************************************************** - * - * Handle the network interface interrupts. - * - */ -static irqreturn_t -de620_interrupt(int irq_in, void *dev_id) -{ - struct net_device *dev = dev_id; - byte irq_status; - int bogus_count = 0; - int again = 0; - - spin_lock(&de620_lock); - - /* Read the status register (_not_ the status port) */ - irq_status = de620_get_register(dev, R_STS); - - pr_debug("de620_interrupt (%2.2X)\n", irq_status); - - if (irq_status & RXGOOD) { - do { - again = de620_rx_intr(dev); - pr_debug("again=%d\n", again); - } - while (again && (++bogus_count < 100)); - } - - if(de620_tx_buffs(dev) != (TXBF0 | TXBF1)) - netif_wake_queue(dev); - - spin_unlock(&de620_lock); - return IRQ_HANDLED; -} - -/************************************** - * - * Get a packet from the adapter - * - * Send it "upstairs" - * - */ -static int de620_rx_intr(struct net_device *dev) -{ - struct header_buf { - byte status; - byte Rx_NextPage; - unsigned short Rx_ByteCount; - } header_buf; - struct sk_buff *skb; - int size; - byte *buffer; - byte pagelink; - byte curr_page; - - pr_debug("de620_rx_intr: next_rx_page = %d\n", next_rx_page); - - /* Tell the adapter that we are going to read data, and from where */ - de620_send_command(dev, W_CR | RRN); - de620_set_register(dev, W_RSA1, next_rx_page); - de620_set_register(dev, W_RSA0, 0); - - /* Deep breath, and away we goooooo */ - de620_read_block(dev, (byte *)&header_buf, sizeof(struct header_buf)); - pr_debug("page status=0x%02x, nextpage=%d, packetsize=%d\n", - header_buf.status, header_buf.Rx_NextPage, - header_buf.Rx_ByteCount); - - /* Plausible page header? */ - pagelink = header_buf.Rx_NextPage; - if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) { - /* Ouch... Forget it! Skip all and start afresh... */ - printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name); - /* You win some, you lose some. And sometimes plenty... */ - adapter_init(dev); - netif_wake_queue(dev); - dev->stats.rx_over_errors++; - return 0; - } - - /* OK, this look good, so far. Let's see if it's consistent... */ - /* Let's compute the start of the next packet, based on where we are */ - pagelink = next_rx_page + - ((header_buf.Rx_ByteCount + (4 - 1 + 0x100)) >> 8); - - /* Are we going to wrap around the page counter? */ - if (pagelink > last_rx_page) - pagelink -= (last_rx_page - first_rx_page + 1); - - /* Is the _computed_ next page number equal to what the adapter says? */ - if (pagelink != header_buf.Rx_NextPage) { - /* Naah, we'll skip this packet. Probably bogus data as well */ - printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name); - next_rx_page = header_buf.Rx_NextPage; /* at least a try... */ - de620_send_command(dev, W_DUMMY); - de620_set_register(dev, W_NPRF, next_rx_page); - dev->stats.rx_over_errors++; - return 0; - } - next_rx_page = pagelink; - - size = header_buf.Rx_ByteCount - 4; - if ((size < RUNT) || (GIANT < size)) { - printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size); - } - else { /* Good packet? */ - skb = netdev_alloc_skb(dev, size + 2); - if (skb == NULL) { /* Yeah, but no place to put it... */ - printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size); - dev->stats.rx_dropped++; - } - else { /* Yep! Go get it! */ - skb_reserve(skb,2); /* Align */ - /* skb->data points to the start of sk_buff data area */ - buffer = skb_put(skb,size); - /* copy the packet into the buffer */ - de620_read_block(dev, buffer, size); - pr_debug("Read %d bytes\n", size); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); /* deliver it "upstairs" */ - /* count all receives */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += size; - } - } - - /* Let's peek ahead to see if we have read the last current packet */ - /* NOTE! We're _not_ checking the 'EMPTY'-flag! This seems better... */ - curr_page = de620_get_register(dev, R_CPR); - de620_set_register(dev, W_NPRF, next_rx_page); - pr_debug("next_rx_page=%d CPR=%d\n", next_rx_page, curr_page); - - return next_rx_page != curr_page; /* That was slightly tricky... */ -} - -/********************************************* - * - * Reset the adapter to a known state - * - */ -static int adapter_init(struct net_device *dev) -{ - int i; - static int was_down; - - if ((nic_data.Model == 3) || (nic_data.Model == 0)) { /* CT */ - EIPRegister = NCTL0; - if (nic_data.Media != 1) - EIPRegister |= NIS0; /* not BNC */ - } - else if (nic_data.Model == 2) { /* UTP */ - EIPRegister = NCTL0 | NIS0; - } - - if (utp) - EIPRegister = NCTL0 | NIS0; - if (bnc) - EIPRegister = NCTL0; - - de620_send_command(dev, W_CR | RNOP | CLEAR); - de620_send_command(dev, W_CR | RNOP); - - de620_set_register(dev, W_SCR, SCR_DEF); - /* disable recv to wait init */ - de620_set_register(dev, W_TCR, RXOFF); - - /* Set the node ID in the adapter */ - for (i = 0; i < 6; ++i) { /* W_PARn = 0xaa + n */ - de620_set_register(dev, W_PAR0 + i, dev->dev_addr[i]); - } - - de620_set_register(dev, W_EIP, EIPRegister); - - next_rx_page = first_rx_page = DE620_RX_START_PAGE; - if (nic_data.RAM_Size) - last_rx_page = nic_data.RAM_Size - 1; - else /* 64k RAM */ - last_rx_page = 255; - - de620_set_register(dev, W_SPR, first_rx_page); /* Start Page Register*/ - de620_set_register(dev, W_EPR, last_rx_page); /* End Page Register */ - de620_set_register(dev, W_CPR, first_rx_page);/*Current Page Register*/ - de620_send_command(dev, W_NPR | first_rx_page); /* Next Page Register*/ - de620_send_command(dev, W_DUMMY); - de620_set_delay(dev); - - /* Final sanity check: Anybody out there? */ - /* Let's hope some bits from the statusregister make a good check */ -#define CHECK_MASK ( 0 | TXSUC | T16 | 0 | RXCRC | RXSHORT | 0 | 0 ) -#define CHECK_OK ( 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 ) - /* success: X 0 0 X 0 0 X X */ - /* ignore: EEDI RXGOOD COLS LNKS*/ - - if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) { - printk(KERN_ERR "%s: Something has happened to the DE-620! Please check it" -#ifdef SHUTDOWN_WHEN_LOST - " and do a new ifconfig" -#endif - "! (%02x)\n", dev->name, i); -#ifdef SHUTDOWN_WHEN_LOST - /* Goodbye, cruel world... */ - dev->flags &= ~IFF_UP; - de620_close(dev); -#endif - was_down = 1; - return 1; /* failed */ - } - if (was_down) { - printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name); - was_down = 0; - } - - /* All OK, go ahead... */ - de620_set_register(dev, W_TCR, TCR_DEF); - - return 0; /* all ok */ -} - -static const struct net_device_ops de620_netdev_ops = { - .ndo_open = de620_open, - .ndo_stop = de620_close, - .ndo_start_xmit = de620_start_xmit, - .ndo_tx_timeout = de620_timeout, - .ndo_set_rx_mode = de620_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/****************************************************************************** - * - * Only start-up code below - * - */ -/**************************************** - * - * Check if there is a DE-620 connected - */ -struct net_device * __init de620_probe(int unit) -{ - byte checkbyte = 0xa5; - struct net_device *dev; - int err = -ENOMEM; - int i; - - dev = alloc_etherdev(0); - if (!dev) - goto out; - - spin_lock_init(&de620_lock); - - /* - * This is where the base_addr and irq gets set. - * Tunable at compile-time and insmod-time - */ - dev->base_addr = io; - dev->irq = irq; - - /* allow overriding parameters on command line */ - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - } - - pr_debug("%s", version); - - printk(KERN_INFO "D-Link DE-620 pocket adapter"); - - if (!request_region(dev->base_addr, 3, "de620")) { - printk(" io 0x%3lX, which is busy.\n", dev->base_addr); - err = -EBUSY; - goto out1; - } - - /* Initially, configure basic nibble mode, so we can read the EEPROM */ - NIC_Cmd = DEF_NIC_CMD; - de620_set_register(dev, W_EIP, EIPRegister); - - /* Anybody out there? */ - de620_set_register(dev, W_CPR, checkbyte); - checkbyte = de620_get_register(dev, R_CPR); - - if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) { - printk(" not identified in the printer port\n"); - err = -ENODEV; - goto out2; - } - - /* else, got it! */ - dev->dev_addr[0] = nic_data.NodeID[0]; - for (i = 1; i < ETH_ALEN; i++) { - dev->dev_addr[i] = nic_data.NodeID[i]; - dev->broadcast[i] = 0xff; - } - - printk(", Ethernet Address: %pM", dev->dev_addr); - - printk(" (%dk RAM,", - (nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64); - - if (nic_data.Media == 1) - printk(" BNC)\n"); - else - printk(" UTP)\n"); - - dev->netdev_ops = &de620_netdev_ops; - dev->watchdog_timeo = HZ*2; - - /* base_addr and irq are already set, see above! */ - - /* dump eeprom */ - pr_debug("\nEEPROM contents:\n" - "RAM_Size = 0x%02X\n" - "NodeID = %pM\n" - "Model = %d\n" - "Media = %d\n" - "SCR = 0x%02x\n", nic_data.RAM_Size, nic_data.NodeID, - nic_data.Model, nic_data.Media, nic_data.SCR); - - err = register_netdev(dev); - if (err) - goto out2; - return dev; - -out2: - release_region(dev->base_addr, 3); -out1: - free_netdev(dev); -out: - return ERR_PTR(err); -} - -/********************************** - * - * Read info from on-board EEPROM - * - * Note: Bitwise serial I/O to/from the EEPROM vi the status _register_! - */ -#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister); - -static unsigned short __init ReadAWord(struct net_device *dev, int from) -{ - unsigned short data; - int nbits; - - /* cs [__~~] SET SEND STATE */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 0); sendit(dev, 1); sendit(dev, 5); sendit(dev, 4); - - /* Send the 9-bit address from where we want to read the 16-bit word */ - for (nbits = 9; nbits > 0; --nbits, from <<= 1) { - if (from & 0x0100) { /* bit set? */ - /* cs [~~~~] SEND 1 */ - /* di [~~~~] */ - /* sck [_~~_] */ - sendit(dev, 6); sendit(dev, 7); sendit(dev, 7); sendit(dev, 6); - } - else { - /* cs [~~~~] SEND 0 */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); - } - } - - /* Shift in the 16-bit word. The bits appear serially in EEDI (=0x80) */ - for (data = 0, nbits = 16; nbits > 0; --nbits) { - /* cs [~~~~] SEND 0 */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 4); sendit(dev, 5); sendit(dev, 5); sendit(dev, 4); - data = (data << 1) | ((de620_get_register(dev, R_STS) & EEDI) >> 7); - } - /* cs [____] RESET SEND STATE */ - /* di [____] */ - /* sck [_~~_] */ - sendit(dev, 0); sendit(dev, 1); sendit(dev, 1); sendit(dev, 0); - - return data; -} - -static int __init read_eeprom(struct net_device *dev) -{ - unsigned short wrd; - - /* D-Link Ethernet addresses are in the series 00:80:c8:7X:XX:XX:XX */ - wrd = ReadAWord(dev, 0x1aa); /* bytes 0 + 1 of NodeID */ - if (!clone && (wrd != htons(0x0080))) /* Valid D-Link ether sequence? */ - return -1; /* Nope, not a DE-620 */ - nic_data.NodeID[0] = wrd & 0xff; - nic_data.NodeID[1] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ab); /* bytes 2 + 3 of NodeID */ - if (!clone && ((wrd & 0xff) != 0xc8)) /* Valid D-Link ether sequence? */ - return -1; /* Nope, not a DE-620 */ - nic_data.NodeID[2] = wrd & 0xff; - nic_data.NodeID[3] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ac); /* bytes 4 + 5 of NodeID */ - nic_data.NodeID[4] = wrd & 0xff; - nic_data.NodeID[5] = wrd >> 8; - - wrd = ReadAWord(dev, 0x1ad); /* RAM size in pages (256 bytes). 0 = 64k */ - nic_data.RAM_Size = (wrd >> 8); - - wrd = ReadAWord(dev, 0x1ae); /* hardware model (CT = 3) */ - nic_data.Model = (wrd & 0xff); - - wrd = ReadAWord(dev, 0x1af); /* media (indicates BNC/UTP) */ - nic_data.Media = (wrd & 0xff); - - wrd = ReadAWord(dev, 0x1a8); /* System Configuration Register */ - nic_data.SCR = (wrd >> 8); - - return 0; /* no errors */ -} - -/****************************************************************************** - * - * Loadable module skeleton - * - */ -#ifdef MODULE -static struct net_device *de620_dev; - -int __init init_module(void) -{ - de620_dev = de620_probe(-1); - if (IS_ERR(de620_dev)) - return PTR_ERR(de620_dev); - return 0; -} - -void cleanup_module(void) -{ - unregister_netdev(de620_dev); - release_region(de620_dev->base_addr, 3); - free_netdev(de620_dev); -} -#endif /* MODULE */ -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.h b/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.h deleted file mode 100644 index e8d9a88f..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/de620.h +++ /dev/null @@ -1,117 +0,0 @@ -/********************************************************* - * * - * Definition of D-Link DE-620 Ethernet Pocket adapter * - * * - *********************************************************/ - -/* DE-620's CMD port Command */ -#define CS0 0x08 /* 1->0 command strobe */ -#define ICEN 0x04 /* 0=enable DL3520 host interface */ -#define DS0 0x02 /* 1->0 data strobe 0 */ -#define DS1 0x01 /* 1->0 data strobe 1 */ - -#define WDIR 0x20 /* general 0=read 1=write */ -#define RDIR 0x00 /* (not 100% confirm ) */ -#define PS2WDIR 0x00 /* ps/2 mode 1=read, 0=write */ -#define PS2RDIR 0x20 - -#define IRQEN 0x10 /* 1 = enable printer IRQ line */ -#define SELECTIN 0x08 /* 1 = select printer */ -#define INITP 0x04 /* 0 = initial printer */ -#define AUTOFEED 0x02 /* 1 = printer auto form feed */ -#define STROBE 0x01 /* 0->1 data strobe */ - -#define RESET 0x08 -#define NIS0 0x20 /* 0 = BNC, 1 = UTP */ -#define NCTL0 0x10 - -/* DE-620 DIC Command */ -#define W_DUMMY 0x00 /* DIC reserved command */ -#define W_CR 0x20 /* DIC write command register */ -#define W_NPR 0x40 /* DIC write Next Page Register */ -#define W_TBR 0x60 /* DIC write Tx Byte Count 1 reg */ -#define W_RSA 0x80 /* DIC write Remote Start Addr 1 */ - -/* DE-620's STAT port bits 7-4 */ -#define EMPTY 0x80 /* 1 = receive buffer empty */ -#define INTLEVEL 0x40 /* 1 = interrupt level is high */ -#define TXBF1 0x20 /* 1 = transmit buffer 1 is in use */ -#define TXBF0 0x10 /* 1 = transmit buffer 0 is in use */ -#define READY 0x08 /* 1 = h/w ready to accept cmd/data */ - -/* IDC 1 Command */ -#define W_RSA1 0xa0 /* write remote start address 1 */ -#define W_RSA0 0xa1 /* write remote start address 0 */ -#define W_NPRF 0xa2 /* write next page register NPR15-NPR8 */ -#define W_DFR 0xa3 /* write delay factor register */ -#define W_CPR 0xa4 /* write current page register */ -#define W_SPR 0xa5 /* write start page register */ -#define W_EPR 0xa6 /* write end page register */ -#define W_SCR 0xa7 /* write system configuration register */ -#define W_TCR 0xa8 /* write Transceiver Configuration reg */ -#define W_EIP 0xa9 /* write EEPM Interface port */ -#define W_PAR0 0xaa /* write physical address register 0 */ -#define W_PAR1 0xab /* write physical address register 1 */ -#define W_PAR2 0xac /* write physical address register 2 */ -#define W_PAR3 0xad /* write physical address register 3 */ -#define W_PAR4 0xae /* write physical address register 4 */ -#define W_PAR5 0xaf /* write physical address register 5 */ - -/* IDC 2 Command */ -#define R_STS 0xc0 /* read status register */ -#define R_CPR 0xc1 /* read current page register */ -#define R_BPR 0xc2 /* read boundary page register */ -#define R_TDR 0xc3 /* read time domain reflectometry reg */ - -/* STATUS Register */ -#define EEDI 0x80 /* EEPM DO pin */ -#define TXSUC 0x40 /* tx success */ -#define T16 0x20 /* tx fail 16 times */ -#define TS1 0x40 /* 0=Tx success, 1=T16 */ -#define TS0 0x20 /* 0=Tx success, 1=T16 */ -#define RXGOOD 0x10 /* rx a good packet */ -#define RXCRC 0x08 /* rx a CRC error packet */ -#define RXSHORT 0x04 /* rx a short packet */ -#define COLS 0x02 /* coaxial collision status */ -#define LNKS 0x01 /* UTP link status */ - -/* Command Register */ -#define CLEAR 0x10 /* reset part of hardware */ -#define NOPER 0x08 /* No Operation */ -#define RNOP 0x08 -#define RRA 0x06 /* After RR then auto-advance NPR & BPR(=NPR-1) */ -#define RRN 0x04 /* Normal Remote Read mode */ -#define RW1 0x02 /* Remote Write tx buffer 1 ( page 6 - 11 ) */ -#define RW0 0x00 /* Remote Write tx buffer 0 ( page 0 - 5 ) */ -#define TXEN 0x01 /* 0->1 tx enable */ - -/* System Configuration Register */ -#define TESTON 0x80 /* test host data transfer reliability */ -#define SLEEP 0x40 /* sleep mode */ -#if 0 -#define FASTMODE 0x04 /* fast mode for intel 82360SL fast mode */ -#define BYTEMODE 0x02 /* byte mode */ -#else -#define FASTMODE 0x20 /* fast mode for intel 82360SL fast mode */ -#define BYTEMODE 0x10 /* byte mode */ -#endif -#define NIBBLEMODE 0x00 /* nibble mode */ -#define IRQINV 0x08 /* turn off IRQ line inverter */ -#define IRQNML 0x00 /* turn on IRQ line inverter */ -#define INTON 0x04 -#define AUTOFFSET 0x02 /* auto shift address to TPR+12 */ -#define AUTOTX 0x01 /* auto tx when leave RW mode */ - -/* Transceiver Configuration Register */ -#define JABBER 0x80 /* generate jabber condition */ -#define TXSUCINT 0x40 /* enable tx success interrupt */ -#define T16INT 0x20 /* enable T16 interrupt */ -#define RXERRPKT 0x10 /* accept CRC error or short packet */ -#define EXTERNALB2 0x0C /* external loopback 2 */ -#define EXTERNALB1 0x08 /* external loopback 1 */ -#define INTERNALB 0x04 /* internal loopback */ -#define NMLOPERATE 0x00 /* normal operation */ -#define RXPBM 0x03 /* rx physical, broadcast, multicast */ -#define RXPB 0x02 /* rx physical, broadcast */ -#define RXALL 0x01 /* rx all packet */ -#define RXOFF 0x00 /* rx disable */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.c b/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.c deleted file mode 100644 index 2e09edb9..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.c +++ /dev/null @@ -1,1787 +0,0 @@ -/* D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */ -/* - Copyright (c) 2001, 2002 by D-Link Corporation - Written by Edward Peng.<edward_peng@dlink.com.tw> - Created 03-May-2001, base on Linux' sundance.c. - - 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. -*/ - -#define DRV_NAME "DL2000/TC902x-based linux driver" -#define DRV_VERSION "v1.19" -#define DRV_RELDATE "2007/08/12" -#include "dl2k.h" -#include <linux/dma-mapping.h> - -static char version[] __devinitdata = - KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n"; -#define MAX_UNITS 8 -static int mtu[MAX_UNITS]; -static int vlan[MAX_UNITS]; -static int jumbo[MAX_UNITS]; -static char *media[MAX_UNITS]; -static int tx_flow=-1; -static int rx_flow=-1; -static int copy_thresh; -static int rx_coalesce=10; /* Rx frame count each interrupt */ -static int rx_timeout=200; /* Rx DMA wait time in 640ns increments */ -static int tx_coalesce=16; /* HW xmit count each TxDMAComplete */ - - -MODULE_AUTHOR ("Edward Peng"); -MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter"); -MODULE_LICENSE("GPL"); -module_param_array(mtu, int, NULL, 0); -module_param_array(media, charp, NULL, 0); -module_param_array(vlan, int, NULL, 0); -module_param_array(jumbo, int, NULL, 0); -module_param(tx_flow, int, 0); -module_param(rx_flow, int, 0); -module_param(copy_thresh, int, 0); -module_param(rx_coalesce, int, 0); /* Rx frame count each interrupt */ -module_param(rx_timeout, int, 0); /* Rx DMA wait time in 64ns increments */ -module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */ - - -/* Enable the default interrupts */ -#define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxDMAComplete| \ - UpdateStats | LinkEvent) -#define EnableInt() \ -writew(DEFAULT_INTR, ioaddr + IntEnable) - -static const int max_intrloop = 50; -static const int multicast_filter_limit = 0x40; - -static int rio_open (struct net_device *dev); -static void rio_timer (unsigned long data); -static void rio_tx_timeout (struct net_device *dev); -static void alloc_list (struct net_device *dev); -static netdev_tx_t start_xmit (struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rio_interrupt (int irq, void *dev_instance); -static void rio_free_tx (struct net_device *dev, int irq); -static void tx_error (struct net_device *dev, int tx_status); -static int receive_packet (struct net_device *dev); -static void rio_error (struct net_device *dev, int int_status); -static int change_mtu (struct net_device *dev, int new_mtu); -static void set_multicast (struct net_device *dev); -static struct net_device_stats *get_stats (struct net_device *dev); -static int clear_stats (struct net_device *dev); -static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static int rio_close (struct net_device *dev); -static int find_miiphy (struct net_device *dev); -static int parse_eeprom (struct net_device *dev); -static int read_eeprom (long ioaddr, int eep_addr); -static int mii_wait_link (struct net_device *dev, int wait); -static int mii_set_media (struct net_device *dev); -static int mii_get_media (struct net_device *dev); -static int mii_set_media_pcs (struct net_device *dev); -static int mii_get_media_pcs (struct net_device *dev); -static int mii_read (struct net_device *dev, int phy_addr, int reg_num); -static int mii_write (struct net_device *dev, int phy_addr, int reg_num, - u16 data); - -static const struct ethtool_ops ethtool_ops; - -static const struct net_device_ops netdev_ops = { - .ndo_open = rio_open, - .ndo_start_xmit = start_xmit, - .ndo_stop = rio_close, - .ndo_get_stats = get_stats, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_set_rx_mode = set_multicast, - .ndo_do_ioctl = rio_ioctl, - .ndo_tx_timeout = rio_tx_timeout, - .ndo_change_mtu = change_mtu, -}; - -static int __devinit -rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *dev; - struct netdev_private *np; - static int card_idx; - int chip_idx = ent->driver_data; - int err, irq; - long ioaddr; - static int version_printed; - void *ring_space; - dma_addr_t ring_dma; - - if (!version_printed++) - printk ("%s", version); - - err = pci_enable_device (pdev); - if (err) - return err; - - irq = pdev->irq; - err = pci_request_regions (pdev, "dl2k"); - if (err) - goto err_out_disable; - - pci_set_master (pdev); - dev = alloc_etherdev (sizeof (*np)); - if (!dev) { - err = -ENOMEM; - goto err_out_res; - } - SET_NETDEV_DEV(dev, &pdev->dev); - -#ifdef MEM_MAPPING - ioaddr = pci_resource_start (pdev, 1); - ioaddr = (long) ioremap (ioaddr, RIO_IO_SIZE); - if (!ioaddr) { - err = -ENOMEM; - goto err_out_dev; - } -#else - ioaddr = pci_resource_start (pdev, 0); -#endif - dev->base_addr = ioaddr; - dev->irq = irq; - np = netdev_priv(dev); - np->chip_id = chip_idx; - np->pdev = pdev; - spin_lock_init (&np->tx_lock); - spin_lock_init (&np->rx_lock); - - /* Parse manual configuration */ - np->an_enable = 1; - np->tx_coalesce = 1; - if (card_idx < MAX_UNITS) { - if (media[card_idx] != NULL) { - np->an_enable = 0; - if (strcmp (media[card_idx], "auto") == 0 || - strcmp (media[card_idx], "autosense") == 0 || - strcmp (media[card_idx], "0") == 0 ) { - np->an_enable = 2; - } else if (strcmp (media[card_idx], "100mbps_fd") == 0 || - strcmp (media[card_idx], "4") == 0) { - np->speed = 100; - np->full_duplex = 1; - } else if (strcmp (media[card_idx], "100mbps_hd") == 0 || - strcmp (media[card_idx], "3") == 0) { - np->speed = 100; - np->full_duplex = 0; - } else if (strcmp (media[card_idx], "10mbps_fd") == 0 || - strcmp (media[card_idx], "2") == 0) { - np->speed = 10; - np->full_duplex = 1; - } else if (strcmp (media[card_idx], "10mbps_hd") == 0 || - strcmp (media[card_idx], "1") == 0) { - np->speed = 10; - np->full_duplex = 0; - } else if (strcmp (media[card_idx], "1000mbps_fd") == 0 || - strcmp (media[card_idx], "6") == 0) { - np->speed=1000; - np->full_duplex=1; - } else if (strcmp (media[card_idx], "1000mbps_hd") == 0 || - strcmp (media[card_idx], "5") == 0) { - np->speed = 1000; - np->full_duplex = 0; - } else { - np->an_enable = 1; - } - } - if (jumbo[card_idx] != 0) { - np->jumbo = 1; - dev->mtu = MAX_JUMBO; - } else { - np->jumbo = 0; - if (mtu[card_idx] > 0 && mtu[card_idx] < PACKET_SIZE) - dev->mtu = mtu[card_idx]; - } - np->vlan = (vlan[card_idx] > 0 && vlan[card_idx] < 4096) ? - vlan[card_idx] : 0; - if (rx_coalesce > 0 && rx_timeout > 0) { - np->rx_coalesce = rx_coalesce; - np->rx_timeout = rx_timeout; - np->coalesce = 1; - } - np->tx_flow = (tx_flow == 0) ? 0 : 1; - np->rx_flow = (rx_flow == 0) ? 0 : 1; - - if (tx_coalesce < 1) - tx_coalesce = 1; - else if (tx_coalesce > TX_RING_SIZE-1) - tx_coalesce = TX_RING_SIZE - 1; - } - dev->netdev_ops = &netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - SET_ETHTOOL_OPS(dev, ðtool_ops); -#if 0 - dev->features = NETIF_F_IP_CSUM; -#endif - pci_set_drvdata (pdev, dev); - - ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma); - if (!ring_space) - goto err_out_iounmap; - np->tx_ring = ring_space; - np->tx_ring_dma = ring_dma; - - ring_space = pci_alloc_consistent (pdev, RX_TOTAL_SIZE, &ring_dma); - if (!ring_space) - goto err_out_unmap_tx; - np->rx_ring = ring_space; - np->rx_ring_dma = ring_dma; - - /* Parse eeprom data */ - parse_eeprom (dev); - - /* Find PHY address */ - err = find_miiphy (dev); - if (err) - goto err_out_unmap_rx; - - /* Fiber device? */ - np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0; - np->link_status = 0; - /* Set media and reset PHY */ - if (np->phy_media) { - /* default Auto-Negotiation for fiber deivices */ - if (np->an_enable == 2) { - np->an_enable = 1; - } - mii_set_media_pcs (dev); - } else { - /* Auto-Negotiation is mandatory for 1000BASE-T, - IEEE 802.3ab Annex 28D page 14 */ - if (np->speed == 1000) - np->an_enable = 1; - mii_set_media (dev); - } - - err = register_netdev (dev); - if (err) - goto err_out_unmap_rx; - - card_idx++; - - printk (KERN_INFO "%s: %s, %pM, IRQ %d\n", - dev->name, np->name, dev->dev_addr, irq); - if (tx_coalesce > 1) - printk(KERN_INFO "tx_coalesce:\t%d packets\n", - tx_coalesce); - if (np->coalesce) - printk(KERN_INFO - "rx_coalesce:\t%d packets\n" - "rx_timeout: \t%d ns\n", - np->rx_coalesce, np->rx_timeout*640); - if (np->vlan) - printk(KERN_INFO "vlan(id):\t%d\n", np->vlan); - return 0; - - err_out_unmap_rx: - pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); - err_out_unmap_tx: - pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); - err_out_iounmap: -#ifdef MEM_MAPPING - iounmap ((void *) ioaddr); - - err_out_dev: -#endif - free_netdev (dev); - - err_out_res: - pci_release_regions (pdev); - - err_out_disable: - pci_disable_device (pdev); - return err; -} - -static int -find_miiphy (struct net_device *dev) -{ - int i, phy_found = 0; - struct netdev_private *np; - long ioaddr; - np = netdev_priv(dev); - ioaddr = dev->base_addr; - np->phy_addr = 1; - - for (i = 31; i >= 0; i--) { - int mii_status = mii_read (dev, i, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - np->phy_addr = i; - phy_found++; - } - } - if (!phy_found) { - printk (KERN_ERR "%s: No MII PHY found!\n", dev->name); - return -ENODEV; - } - return 0; -} - -static int -parse_eeprom (struct net_device *dev) -{ - int i, j; - long ioaddr = dev->base_addr; - u8 sromdata[256]; - u8 *psib; - u32 crc; - PSROM_t psrom = (PSROM_t) sromdata; - struct netdev_private *np = netdev_priv(dev); - - int cid, next; - -#ifdef MEM_MAPPING - ioaddr = pci_resource_start (np->pdev, 0); -#endif - /* Read eeprom */ - for (i = 0; i < 128; i++) { - ((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom (ioaddr, i)); - } -#ifdef MEM_MAPPING - ioaddr = dev->base_addr; -#endif - if (np->pdev->vendor == PCI_VENDOR_ID_DLINK) { /* D-Link Only */ - /* Check CRC */ - crc = ~ether_crc_le (256 - 4, sromdata); - if (psrom->crc != cpu_to_le32(crc)) { - printk (KERN_ERR "%s: EEPROM data CRC error.\n", - dev->name); - return -1; - } - } - - /* Set MAC address */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = psrom->mac_addr[i]; - - if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) { - return 0; - } - - /* Parse Software Information Block */ - i = 0x30; - psib = (u8 *) sromdata; - do { - cid = psib[i++]; - next = psib[i++]; - if ((cid == 0 && next == 0) || (cid == 0xff && next == 0xff)) { - printk (KERN_ERR "Cell data error\n"); - return -1; - } - switch (cid) { - case 0: /* Format version */ - break; - case 1: /* End of cell */ - return 0; - case 2: /* Duplex Polarity */ - np->duplex_polarity = psib[i]; - writeb (readb (ioaddr + PhyCtrl) | psib[i], - ioaddr + PhyCtrl); - break; - case 3: /* Wake Polarity */ - np->wake_polarity = psib[i]; - break; - case 9: /* Adapter description */ - j = (next - i > 255) ? 255 : next - i; - memcpy (np->name, &(psib[i]), j); - break; - case 4: - case 5: - case 6: - case 7: - case 8: /* Reversed */ - break; - default: /* Unknown cell */ - return -1; - } - i = next; - } while (1); - - return 0; -} - -static int -rio_open (struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - long ioaddr = dev->base_addr; - int i; - u16 macctrl; - - i = request_irq (dev->irq, rio_interrupt, IRQF_SHARED, dev->name, dev); - if (i) - return i; - - /* Reset all logic functions */ - writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset, - ioaddr + ASICCtrl + 2); - mdelay(10); - - /* DebugCtrl bit 4, 5, 9 must set */ - writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl); - - /* Jumbo frame */ - if (np->jumbo != 0) - writew (MAX_JUMBO+14, ioaddr + MaxFrameSize); - - alloc_list (dev); - - /* Get station address */ - for (i = 0; i < 6; i++) - writeb (dev->dev_addr[i], ioaddr + StationAddr0 + i); - - set_multicast (dev); - if (np->coalesce) { - writel (np->rx_coalesce | np->rx_timeout << 16, - ioaddr + RxDMAIntCtrl); - } - /* Set RIO to poll every N*320nsec. */ - writeb (0x20, ioaddr + RxDMAPollPeriod); - writeb (0xff, ioaddr + TxDMAPollPeriod); - writeb (0x30, ioaddr + RxDMABurstThresh); - writeb (0x30, ioaddr + RxDMAUrgentThresh); - writel (0x0007ffff, ioaddr + RmonStatMask); - /* clear statistics */ - clear_stats (dev); - - /* VLAN supported */ - if (np->vlan) { - /* priority field in RxDMAIntCtrl */ - writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10, - ioaddr + RxDMAIntCtrl); - /* VLANId */ - writew (np->vlan, ioaddr + VLANId); - /* Length/Type should be 0x8100 */ - writel (0x8100 << 16 | np->vlan, ioaddr + VLANTag); - /* Enable AutoVLANuntagging, but disable AutoVLANtagging. - VLAN information tagged by TFC' VID, CFI fields. */ - writel (readl (ioaddr + MACCtrl) | AutoVLANuntagging, - ioaddr + MACCtrl); - } - - init_timer (&np->timer); - np->timer.expires = jiffies + 1*HZ; - np->timer.data = (unsigned long) dev; - np->timer.function = rio_timer; - add_timer (&np->timer); - - /* Start Tx/Rx */ - writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable, - ioaddr + MACCtrl); - - macctrl = 0; - macctrl |= (np->vlan) ? AutoVLANuntagging : 0; - macctrl |= (np->full_duplex) ? DuplexSelect : 0; - macctrl |= (np->tx_flow) ? TxFlowControlEnable : 0; - macctrl |= (np->rx_flow) ? RxFlowControlEnable : 0; - writew(macctrl, ioaddr + MACCtrl); - - netif_start_queue (dev); - - /* Enable default interrupts */ - EnableInt (); - return 0; -} - -static void -rio_timer (unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); - unsigned int entry; - int next_tick = 1*HZ; - unsigned long flags; - - spin_lock_irqsave(&np->rx_lock, flags); - /* Recover rx ring exhausted error */ - if (np->cur_rx - np->old_rx >= RX_RING_SIZE) { - printk(KERN_INFO "Try to recover rx ring exhausted...\n"); - /* Re-allocate skbuffs to fill the descriptor ring */ - for (; np->cur_rx - np->old_rx > 0; np->old_rx++) { - struct sk_buff *skb; - entry = np->old_rx % RX_RING_SIZE; - /* Dropped packets don't need to re-allocate */ - if (np->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb_ip_align(dev, - np->rx_buf_sz); - if (skb == NULL) { - np->rx_ring[entry].fraginfo = 0; - printk (KERN_INFO - "%s: Still unable to re-allocate Rx skbuff.#%d\n", - dev->name, entry); - break; - } - np->rx_skbuff[entry] = skb; - np->rx_ring[entry].fraginfo = - cpu_to_le64 (pci_map_single - (np->pdev, skb->data, np->rx_buf_sz, - PCI_DMA_FROMDEVICE)); - } - np->rx_ring[entry].fraginfo |= - cpu_to_le64((u64)np->rx_buf_sz << 48); - np->rx_ring[entry].status = 0; - } /* end for */ - } /* end if */ - spin_unlock_irqrestore (&np->rx_lock, flags); - np->timer.expires = jiffies + next_tick; - add_timer(&np->timer); -} - -static void -rio_tx_timeout (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - - printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n", - dev->name, readl (ioaddr + TxStatus)); - rio_free_tx(dev, 0); - dev->if_port = 0; - dev->trans_start = jiffies; /* prevent tx timeout */ -} - - /* allocate and initialize Tx and Rx descriptors */ -static void -alloc_list (struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - int i; - - np->cur_rx = np->cur_tx = 0; - np->old_rx = np->old_tx = 0; - np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32); - - /* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */ - for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = NULL; - np->tx_ring[i].status = cpu_to_le64 (TFDDone); - np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma + - ((i+1)%TX_RING_SIZE) * - sizeof (struct netdev_desc)); - } - - /* Initialize Rx descriptors */ - for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma + - ((i + 1) % RX_RING_SIZE) * - sizeof (struct netdev_desc)); - np->rx_ring[i].status = 0; - np->rx_ring[i].fraginfo = 0; - np->rx_skbuff[i] = NULL; - } - - /* Allocate the rx buffers */ - for (i = 0; i < RX_RING_SIZE; i++) { - /* Allocated fixed size of skbuff */ - struct sk_buff *skb; - - skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz); - np->rx_skbuff[i] = skb; - if (skb == NULL) { - printk (KERN_ERR - "%s: alloc_list: allocate Rx buffer error! ", - dev->name); - break; - } - /* Rubicon now supports 40 bits of addressing space. */ - np->rx_ring[i].fraginfo = - cpu_to_le64 ( pci_map_single ( - np->pdev, skb->data, np->rx_buf_sz, - PCI_DMA_FROMDEVICE)); - np->rx_ring[i].fraginfo |= cpu_to_le64((u64)np->rx_buf_sz << 48); - } - - /* Set RFDListPtr */ - writel (np->rx_ring_dma, dev->base_addr + RFDListPtr0); - writel (0, dev->base_addr + RFDListPtr1); -} - -static netdev_tx_t -start_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - struct netdev_desc *txdesc; - unsigned entry; - u32 ioaddr; - u64 tfc_vlan_tag = 0; - - if (np->link_status == 0) { /* Link Down */ - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - ioaddr = dev->base_addr; - entry = np->cur_tx % TX_RING_SIZE; - np->tx_skbuff[entry] = skb; - txdesc = &np->tx_ring[entry]; - -#if 0 - if (skb->ip_summed == CHECKSUM_PARTIAL) { - txdesc->status |= - cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable | - IPChecksumEnable); - } -#endif - if (np->vlan) { - tfc_vlan_tag = VLANTagInsert | - ((u64)np->vlan << 32) | - ((u64)skb->priority << 45); - } - txdesc->fraginfo = cpu_to_le64 (pci_map_single (np->pdev, skb->data, - skb->len, - PCI_DMA_TODEVICE)); - txdesc->fraginfo |= cpu_to_le64((u64)skb->len << 48); - - /* DL2K bug: DMA fails to get next descriptor ptr in 10Mbps mode - * Work around: Always use 1 descriptor in 10Mbps mode */ - if (entry % np->tx_coalesce == 0 || np->speed == 10) - txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | - WordAlignDisable | - TxDMAIndicate | - (1 << FragCountShift)); - else - txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag | - WordAlignDisable | - (1 << FragCountShift)); - - /* TxDMAPollNow */ - writel (readl (ioaddr + DMACtrl) | 0x00001000, ioaddr + DMACtrl); - /* Schedule ISR */ - writel(10000, ioaddr + CountDown); - np->cur_tx = (np->cur_tx + 1) % TX_RING_SIZE; - if ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE - < TX_QUEUE_LEN - 1 && np->speed != 10) { - /* do nothing */ - } else if (!netif_queue_stopped(dev)) { - netif_stop_queue (dev); - } - - /* The first TFDListPtr */ - if (readl (dev->base_addr + TFDListPtr0) == 0) { - writel (np->tx_ring_dma + entry * sizeof (struct netdev_desc), - dev->base_addr + TFDListPtr0); - writel (0, dev->base_addr + TFDListPtr1); - } - - return NETDEV_TX_OK; -} - -static irqreturn_t -rio_interrupt (int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct netdev_private *np; - unsigned int_status; - long ioaddr; - int cnt = max_intrloop; - int handled = 0; - - ioaddr = dev->base_addr; - np = netdev_priv(dev); - while (1) { - int_status = readw (ioaddr + IntStatus); - writew (int_status, ioaddr + IntStatus); - int_status &= DEFAULT_INTR; - if (int_status == 0 || --cnt < 0) - break; - handled = 1; - /* Processing received packets */ - if (int_status & RxDMAComplete) - receive_packet (dev); - /* TxDMAComplete interrupt */ - if ((int_status & (TxDMAComplete|IntRequested))) { - int tx_status; - tx_status = readl (ioaddr + TxStatus); - if (tx_status & 0x01) - tx_error (dev, tx_status); - /* Free used tx skbuffs */ - rio_free_tx (dev, 1); - } - - /* Handle uncommon events */ - if (int_status & - (HostError | LinkEvent | UpdateStats)) - rio_error (dev, int_status); - } - if (np->cur_tx != np->old_tx) - writel (100, ioaddr + CountDown); - return IRQ_RETVAL(handled); -} - -static inline dma_addr_t desc_to_dma(struct netdev_desc *desc) -{ - return le64_to_cpu(desc->fraginfo) & DMA_BIT_MASK(48); -} - -static void -rio_free_tx (struct net_device *dev, int irq) -{ - struct netdev_private *np = netdev_priv(dev); - int entry = np->old_tx % TX_RING_SIZE; - int tx_use = 0; - unsigned long flag = 0; - - if (irq) - spin_lock(&np->tx_lock); - else - spin_lock_irqsave(&np->tx_lock, flag); - - /* Free used tx skbuffs */ - while (entry != np->cur_tx) { - struct sk_buff *skb; - - if (!(np->tx_ring[entry].status & cpu_to_le64(TFDDone))) - break; - skb = np->tx_skbuff[entry]; - pci_unmap_single (np->pdev, - desc_to_dma(&np->tx_ring[entry]), - skb->len, PCI_DMA_TODEVICE); - if (irq) - dev_kfree_skb_irq (skb); - else - dev_kfree_skb (skb); - - np->tx_skbuff[entry] = NULL; - entry = (entry + 1) % TX_RING_SIZE; - tx_use++; - } - if (irq) - spin_unlock(&np->tx_lock); - else - spin_unlock_irqrestore(&np->tx_lock, flag); - np->old_tx = entry; - - /* If the ring is no longer full, clear tx_full and - call netif_wake_queue() */ - - if (netif_queue_stopped(dev) && - ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE - < TX_QUEUE_LEN - 1 || np->speed == 10)) { - netif_wake_queue (dev); - } -} - -static void -tx_error (struct net_device *dev, int tx_status) -{ - struct netdev_private *np; - long ioaddr = dev->base_addr; - int frame_id; - int i; - - np = netdev_priv(dev); - - frame_id = (tx_status & 0xffff0000); - printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", - dev->name, tx_status, frame_id); - np->stats.tx_errors++; - /* Ttransmit Underrun */ - if (tx_status & 0x10) { - np->stats.tx_fifo_errors++; - writew (readw (ioaddr + TxStartThresh) + 0x10, - ioaddr + TxStartThresh); - /* Transmit Underrun need to set TxReset, DMARest, FIFOReset */ - writew (TxReset | DMAReset | FIFOReset | NetworkReset, - ioaddr + ASICCtrl + 2); - /* Wait for ResetBusy bit clear */ - for (i = 50; i > 0; i--) { - if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0) - break; - mdelay (1); - } - rio_free_tx (dev, 1); - /* Reset TFDListPtr */ - writel (np->tx_ring_dma + - np->old_tx * sizeof (struct netdev_desc), - dev->base_addr + TFDListPtr0); - writel (0, dev->base_addr + TFDListPtr1); - - /* Let TxStartThresh stay default value */ - } - /* Late Collision */ - if (tx_status & 0x04) { - np->stats.tx_fifo_errors++; - /* TxReset and clear FIFO */ - writew (TxReset | FIFOReset, ioaddr + ASICCtrl + 2); - /* Wait reset done */ - for (i = 50; i > 0; i--) { - if ((readw (ioaddr + ASICCtrl + 2) & ResetBusy) == 0) - break; - mdelay (1); - } - /* Let TxStartThresh stay default value */ - } - /* Maximum Collisions */ -#ifdef ETHER_STATS - if (tx_status & 0x08) - np->stats.collisions16++; -#else - if (tx_status & 0x08) - np->stats.collisions++; -#endif - /* Restart the Tx */ - writel (readw (dev->base_addr + MACCtrl) | TxEnable, ioaddr + MACCtrl); -} - -static int -receive_packet (struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - int entry = np->cur_rx % RX_RING_SIZE; - int cnt = 30; - - /* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */ - while (1) { - struct netdev_desc *desc = &np->rx_ring[entry]; - int pkt_len; - u64 frame_status; - - if (!(desc->status & cpu_to_le64(RFDDone)) || - !(desc->status & cpu_to_le64(FrameStart)) || - !(desc->status & cpu_to_le64(FrameEnd))) - break; - - /* Chip omits the CRC. */ - frame_status = le64_to_cpu(desc->status); - pkt_len = frame_status & 0xffff; - if (--cnt < 0) - break; - /* Update rx error statistics, drop packet. */ - if (frame_status & RFS_Errors) { - np->stats.rx_errors++; - if (frame_status & (RxRuntFrame | RxLengthError)) - np->stats.rx_length_errors++; - if (frame_status & RxFCSError) - np->stats.rx_crc_errors++; - if (frame_status & RxAlignmentError && np->speed != 1000) - np->stats.rx_frame_errors++; - if (frame_status & RxFIFOOverrun) - np->stats.rx_fifo_errors++; - } else { - struct sk_buff *skb; - - /* Small skbuffs for short packets */ - if (pkt_len > copy_thresh) { - pci_unmap_single (np->pdev, - desc_to_dma(desc), - np->rx_buf_sz, - PCI_DMA_FROMDEVICE); - skb_put (skb = np->rx_skbuff[entry], pkt_len); - np->rx_skbuff[entry] = NULL; - } else if ((skb = netdev_alloc_skb_ip_align(dev, pkt_len))) { - pci_dma_sync_single_for_cpu(np->pdev, - desc_to_dma(desc), - np->rx_buf_sz, - PCI_DMA_FROMDEVICE); - skb_copy_to_linear_data (skb, - np->rx_skbuff[entry]->data, - pkt_len); - skb_put (skb, pkt_len); - pci_dma_sync_single_for_device(np->pdev, - desc_to_dma(desc), - np->rx_buf_sz, - PCI_DMA_FROMDEVICE); - } - skb->protocol = eth_type_trans (skb, dev); -#if 0 - /* Checksum done by hw, but csum value unavailable. */ - if (np->pdev->pci_rev_id >= 0x0c && - !(frame_status & (TCPError | UDPError | IPError))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } -#endif - netif_rx (skb); - } - entry = (entry + 1) % RX_RING_SIZE; - } - spin_lock(&np->rx_lock); - np->cur_rx = entry; - /* Re-allocate skbuffs to fill the descriptor ring */ - entry = np->old_rx; - while (entry != np->cur_rx) { - struct sk_buff *skb; - /* Dropped packets don't need to re-allocate */ - if (np->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz); - if (skb == NULL) { - np->rx_ring[entry].fraginfo = 0; - printk (KERN_INFO - "%s: receive_packet: " - "Unable to re-allocate Rx skbuff.#%d\n", - dev->name, entry); - break; - } - np->rx_skbuff[entry] = skb; - np->rx_ring[entry].fraginfo = - cpu_to_le64 (pci_map_single - (np->pdev, skb->data, np->rx_buf_sz, - PCI_DMA_FROMDEVICE)); - } - np->rx_ring[entry].fraginfo |= - cpu_to_le64((u64)np->rx_buf_sz << 48); - np->rx_ring[entry].status = 0; - entry = (entry + 1) % RX_RING_SIZE; - } - np->old_rx = entry; - spin_unlock(&np->rx_lock); - return 0; -} - -static void -rio_error (struct net_device *dev, int int_status) -{ - long ioaddr = dev->base_addr; - struct netdev_private *np = netdev_priv(dev); - u16 macctrl; - - /* Link change event */ - if (int_status & LinkEvent) { - if (mii_wait_link (dev, 10) == 0) { - printk (KERN_INFO "%s: Link up\n", dev->name); - if (np->phy_media) - mii_get_media_pcs (dev); - else - mii_get_media (dev); - if (np->speed == 1000) - np->tx_coalesce = tx_coalesce; - else - np->tx_coalesce = 1; - macctrl = 0; - macctrl |= (np->vlan) ? AutoVLANuntagging : 0; - macctrl |= (np->full_duplex) ? DuplexSelect : 0; - macctrl |= (np->tx_flow) ? - TxFlowControlEnable : 0; - macctrl |= (np->rx_flow) ? - RxFlowControlEnable : 0; - writew(macctrl, ioaddr + MACCtrl); - np->link_status = 1; - netif_carrier_on(dev); - } else { - printk (KERN_INFO "%s: Link off\n", dev->name); - np->link_status = 0; - netif_carrier_off(dev); - } - } - - /* UpdateStats statistics registers */ - if (int_status & UpdateStats) { - get_stats (dev); - } - - /* PCI Error, a catastronphic error related to the bus interface - occurs, set GlobalReset and HostReset to reset. */ - if (int_status & HostError) { - printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n", - dev->name, int_status); - writew (GlobalReset | HostReset, ioaddr + ASICCtrl + 2); - mdelay (500); - } -} - -static struct net_device_stats * -get_stats (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct netdev_private *np = netdev_priv(dev); -#ifdef MEM_MAPPING - int i; -#endif - unsigned int stat_reg; - - /* All statistics registers need to be acknowledged, - else statistic overflow could cause problems */ - - np->stats.rx_packets += readl (ioaddr + FramesRcvOk); - np->stats.tx_packets += readl (ioaddr + FramesXmtOk); - np->stats.rx_bytes += readl (ioaddr + OctetRcvOk); - np->stats.tx_bytes += readl (ioaddr + OctetXmtOk); - - np->stats.multicast = readl (ioaddr + McstFramesRcvdOk); - np->stats.collisions += readl (ioaddr + SingleColFrames) - + readl (ioaddr + MultiColFrames); - - /* detailed tx errors */ - stat_reg = readw (ioaddr + FramesAbortXSColls); - np->stats.tx_aborted_errors += stat_reg; - np->stats.tx_errors += stat_reg; - - stat_reg = readw (ioaddr + CarrierSenseErrors); - np->stats.tx_carrier_errors += stat_reg; - np->stats.tx_errors += stat_reg; - - /* Clear all other statistic register. */ - readl (ioaddr + McstOctetXmtOk); - readw (ioaddr + BcstFramesXmtdOk); - readl (ioaddr + McstFramesXmtdOk); - readw (ioaddr + BcstFramesRcvdOk); - readw (ioaddr + MacControlFramesRcvd); - readw (ioaddr + FrameTooLongErrors); - readw (ioaddr + InRangeLengthErrors); - readw (ioaddr + FramesCheckSeqErrors); - readw (ioaddr + FramesLostRxErrors); - readl (ioaddr + McstOctetXmtOk); - readl (ioaddr + BcstOctetXmtOk); - readl (ioaddr + McstFramesXmtdOk); - readl (ioaddr + FramesWDeferredXmt); - readl (ioaddr + LateCollisions); - readw (ioaddr + BcstFramesXmtdOk); - readw (ioaddr + MacControlFramesXmtd); - readw (ioaddr + FramesWEXDeferal); - -#ifdef MEM_MAPPING - for (i = 0x100; i <= 0x150; i += 4) - readl (ioaddr + i); -#endif - readw (ioaddr + TxJumboFrames); - readw (ioaddr + RxJumboFrames); - readw (ioaddr + TCPCheckSumErrors); - readw (ioaddr + UDPCheckSumErrors); - readw (ioaddr + IPCheckSumErrors); - return &np->stats; -} - -static int -clear_stats (struct net_device *dev) -{ - long ioaddr = dev->base_addr; -#ifdef MEM_MAPPING - int i; -#endif - - /* All statistics registers need to be acknowledged, - else statistic overflow could cause problems */ - readl (ioaddr + FramesRcvOk); - readl (ioaddr + FramesXmtOk); - readl (ioaddr + OctetRcvOk); - readl (ioaddr + OctetXmtOk); - - readl (ioaddr + McstFramesRcvdOk); - readl (ioaddr + SingleColFrames); - readl (ioaddr + MultiColFrames); - readl (ioaddr + LateCollisions); - /* detailed rx errors */ - readw (ioaddr + FrameTooLongErrors); - readw (ioaddr + InRangeLengthErrors); - readw (ioaddr + FramesCheckSeqErrors); - readw (ioaddr + FramesLostRxErrors); - - /* detailed tx errors */ - readw (ioaddr + FramesAbortXSColls); - readw (ioaddr + CarrierSenseErrors); - - /* Clear all other statistic register. */ - readl (ioaddr + McstOctetXmtOk); - readw (ioaddr + BcstFramesXmtdOk); - readl (ioaddr + McstFramesXmtdOk); - readw (ioaddr + BcstFramesRcvdOk); - readw (ioaddr + MacControlFramesRcvd); - readl (ioaddr + McstOctetXmtOk); - readl (ioaddr + BcstOctetXmtOk); - readl (ioaddr + McstFramesXmtdOk); - readl (ioaddr + FramesWDeferredXmt); - readw (ioaddr + BcstFramesXmtdOk); - readw (ioaddr + MacControlFramesXmtd); - readw (ioaddr + FramesWEXDeferal); -#ifdef MEM_MAPPING - for (i = 0x100; i <= 0x150; i += 4) - readl (ioaddr + i); -#endif - readw (ioaddr + TxJumboFrames); - readw (ioaddr + RxJumboFrames); - readw (ioaddr + TCPCheckSumErrors); - readw (ioaddr + UDPCheckSumErrors); - readw (ioaddr + IPCheckSumErrors); - return 0; -} - - -static int -change_mtu (struct net_device *dev, int new_mtu) -{ - struct netdev_private *np = netdev_priv(dev); - int max = (np->jumbo) ? MAX_JUMBO : 1536; - - if ((new_mtu < 68) || (new_mtu > max)) { - return -EINVAL; - } - - dev->mtu = new_mtu; - - return 0; -} - -static void -set_multicast (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - u32 hash_table[2]; - u16 rx_mode = 0; - struct netdev_private *np = netdev_priv(dev); - - hash_table[0] = hash_table[1] = 0; - /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ - hash_table[1] |= 0x02000000; - if (dev->flags & IFF_PROMISC) { - /* Receive all frames promiscuously. */ - rx_mode = ReceiveAllFrames; - } else if ((dev->flags & IFF_ALLMULTI) || - (netdev_mc_count(dev) > multicast_filter_limit)) { - /* Receive broadcast and multicast frames */ - rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; - } else if (!netdev_mc_empty(dev)) { - struct netdev_hw_addr *ha; - /* Receive broadcast frames and multicast frames filtering - by Hashtable */ - rx_mode = - ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; - netdev_for_each_mc_addr(ha, dev) { - int bit, index = 0; - int crc = ether_crc_le(ETH_ALEN, ha->addr); - /* The inverted high significant 6 bits of CRC are - used as an index to hashtable */ - for (bit = 0; bit < 6; bit++) - if (crc & (1 << (31 - bit))) - index |= (1 << bit); - hash_table[index / 32] |= (1 << (index % 32)); - } - } else { - rx_mode = ReceiveBroadcast | ReceiveUnicast; - } - if (np->vlan) { - /* ReceiveVLANMatch field in ReceiveMode */ - rx_mode |= ReceiveVLANMatch; - } - - writel (hash_table[0], ioaddr + HashTable0); - writel (hash_table[1], ioaddr + HashTable1); - writew (rx_mode, ioaddr + ReceiveMode); -} - -static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct netdev_private *np = netdev_priv(dev); - strcpy(info->driver, "dl2k"); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(np->pdev)); -} - -static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct netdev_private *np = netdev_priv(dev); - if (np->phy_media) { - /* fiber device */ - cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - } else { - /* copper device */ - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_MII; - cmd->advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| - ADVERTISED_Autoneg | ADVERTISED_MII; - cmd->port = PORT_MII; - cmd->transceiver = XCVR_INTERNAL; - } - if ( np->link_status ) { - ethtool_cmd_speed_set(cmd, np->speed); - cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(cmd, -1); - cmd->duplex = -1; - } - if ( np->an_enable) - cmd->autoneg = AUTONEG_ENABLE; - else - cmd->autoneg = AUTONEG_DISABLE; - - cmd->phy_address = np->phy_addr; - return 0; -} - -static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct netdev_private *np = netdev_priv(dev); - netif_carrier_off(dev); - if (cmd->autoneg == AUTONEG_ENABLE) { - if (np->an_enable) - return 0; - else { - np->an_enable = 1; - mii_set_media(dev); - return 0; - } - } else { - np->an_enable = 0; - if (np->speed == 1000) { - ethtool_cmd_speed_set(cmd, SPEED_100); - cmd->duplex = DUPLEX_FULL; - printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n"); - } - switch (ethtool_cmd_speed(cmd)) { - case SPEED_10: - np->speed = 10; - np->full_duplex = (cmd->duplex == DUPLEX_FULL); - break; - case SPEED_100: - np->speed = 100; - np->full_duplex = (cmd->duplex == DUPLEX_FULL); - break; - case SPEED_1000: /* not supported */ - default: - return -EINVAL; - } - mii_set_media(dev); - } - return 0; -} - -static u32 rio_get_link(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - return np->link_status; -} - -static const struct ethtool_ops ethtool_ops = { - .get_drvinfo = rio_get_drvinfo, - .get_settings = rio_get_settings, - .set_settings = rio_set_settings, - .get_link = rio_get_link, -}; - -static int -rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) -{ - int phy_addr; - struct netdev_private *np = netdev_priv(dev); - struct mii_ioctl_data *miidata = if_mii(rq); - - phy_addr = np->phy_addr; - switch (cmd) { - case SIOCGMIIPHY: - miidata->phy_id = phy_addr; - break; - case SIOCGMIIREG: - miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); - break; - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -#define EEP_READ 0x0200 -#define EEP_BUSY 0x8000 -/* Read the EEPROM word */ -/* We use I/O instruction to read/write eeprom to avoid fail on some machines */ -static int -read_eeprom (long ioaddr, int eep_addr) -{ - int i = 1000; - outw (EEP_READ | (eep_addr & 0xff), ioaddr + EepromCtrl); - while (i-- > 0) { - if (!(inw (ioaddr + EepromCtrl) & EEP_BUSY)) { - return inw (ioaddr + EepromData); - } - } - return 0; -} - -enum phy_ctrl_bits { - MII_READ = 0x00, MII_CLK = 0x01, MII_DATA1 = 0x02, MII_WRITE = 0x04, - MII_DUPLEX = 0x08, -}; - -#define mii_delay() readb(ioaddr) -static void -mii_sendbit (struct net_device *dev, u32 data) -{ - long ioaddr = dev->base_addr + PhyCtrl; - data = (data) ? MII_DATA1 : 0; - data |= MII_WRITE; - data |= (readb (ioaddr) & 0xf8) | MII_WRITE; - writeb (data, ioaddr); - mii_delay (); - writeb (data | MII_CLK, ioaddr); - mii_delay (); -} - -static int -mii_getbit (struct net_device *dev) -{ - long ioaddr = dev->base_addr + PhyCtrl; - u8 data; - - data = (readb (ioaddr) & 0xf8) | MII_READ; - writeb (data, ioaddr); - mii_delay (); - writeb (data | MII_CLK, ioaddr); - mii_delay (); - return ((readb (ioaddr) >> 1) & 1); -} - -static void -mii_send_bits (struct net_device *dev, u32 data, int len) -{ - int i; - for (i = len - 1; i >= 0; i--) { - mii_sendbit (dev, data & (1 << i)); - } -} - -static int -mii_read (struct net_device *dev, int phy_addr, int reg_num) -{ - u32 cmd; - int i; - u32 retval = 0; - - /* Preamble */ - mii_send_bits (dev, 0xffffffff, 32); - /* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */ - /* ST,OP = 0110'b for read operation */ - cmd = (0x06 << 10 | phy_addr << 5 | reg_num); - mii_send_bits (dev, cmd, 14); - /* Turnaround */ - if (mii_getbit (dev)) - goto err_out; - /* Read data */ - for (i = 0; i < 16; i++) { - retval |= mii_getbit (dev); - retval <<= 1; - } - /* End cycle */ - mii_getbit (dev); - return (retval >> 1) & 0xffff; - - err_out: - return 0; -} -static int -mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data) -{ - u32 cmd; - - /* Preamble */ - mii_send_bits (dev, 0xffffffff, 32); - /* ST(2), OP(2), ADDR(5), REG#(5), TA(2), Data(16) total 32 bits */ - /* ST,OP,AAAAA,RRRRR,TA = 0101xxxxxxxxxx10'b = 0x5002 for write */ - cmd = (0x5002 << 16) | (phy_addr << 23) | (reg_num << 18) | data; - mii_send_bits (dev, cmd, 32); - /* End cycle */ - mii_getbit (dev); - return 0; -} -static int -mii_wait_link (struct net_device *dev, int wait) -{ - __u16 bmsr; - int phy_addr; - struct netdev_private *np; - - np = netdev_priv(dev); - phy_addr = np->phy_addr; - - do { - bmsr = mii_read (dev, phy_addr, MII_BMSR); - if (bmsr & BMSR_LSTATUS) - return 0; - mdelay (1); - } while (--wait > 0); - return -1; -} -static int -mii_get_media (struct net_device *dev) -{ - __u16 negotiate; - __u16 bmsr; - __u16 mscr; - __u16 mssr; - int phy_addr; - struct netdev_private *np; - - np = netdev_priv(dev); - phy_addr = np->phy_addr; - - bmsr = mii_read (dev, phy_addr, MII_BMSR); - if (np->an_enable) { - if (!(bmsr & BMSR_ANEGCOMPLETE)) { - /* Auto-Negotiation not completed */ - return -1; - } - negotiate = mii_read (dev, phy_addr, MII_ADVERTISE) & - mii_read (dev, phy_addr, MII_LPA); - mscr = mii_read (dev, phy_addr, MII_CTRL1000); - mssr = mii_read (dev, phy_addr, MII_STAT1000); - if (mscr & ADVERTISE_1000FULL && mssr & LPA_1000FULL) { - np->speed = 1000; - np->full_duplex = 1; - printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n"); - } else if (mscr & ADVERTISE_1000HALF && mssr & LPA_1000HALF) { - np->speed = 1000; - np->full_duplex = 0; - printk (KERN_INFO "Auto 1000 Mbps, Half duplex\n"); - } else if (negotiate & ADVERTISE_100FULL) { - np->speed = 100; - np->full_duplex = 1; - printk (KERN_INFO "Auto 100 Mbps, Full duplex\n"); - } else if (negotiate & ADVERTISE_100HALF) { - np->speed = 100; - np->full_duplex = 0; - printk (KERN_INFO "Auto 100 Mbps, Half duplex\n"); - } else if (negotiate & ADVERTISE_10FULL) { - np->speed = 10; - np->full_duplex = 1; - printk (KERN_INFO "Auto 10 Mbps, Full duplex\n"); - } else if (negotiate & ADVERTISE_10HALF) { - np->speed = 10; - np->full_duplex = 0; - printk (KERN_INFO "Auto 10 Mbps, Half duplex\n"); - } - if (negotiate & ADVERTISE_PAUSE_CAP) { - np->tx_flow &= 1; - np->rx_flow &= 1; - } else if (negotiate & ADVERTISE_PAUSE_ASYM) { - np->tx_flow = 0; - np->rx_flow &= 1; - } - /* else tx_flow, rx_flow = user select */ - } else { - __u16 bmcr = mii_read (dev, phy_addr, MII_BMCR); - switch (bmcr & (BMCR_SPEED100 | BMCR_SPEED1000)) { - case BMCR_SPEED1000: - printk (KERN_INFO "Operating at 1000 Mbps, "); - break; - case BMCR_SPEED100: - printk (KERN_INFO "Operating at 100 Mbps, "); - break; - case 0: - printk (KERN_INFO "Operating at 10 Mbps, "); - } - if (bmcr & BMCR_FULLDPLX) { - printk (KERN_CONT "Full duplex\n"); - } else { - printk (KERN_CONT "Half duplex\n"); - } - } - if (np->tx_flow) - printk(KERN_INFO "Enable Tx Flow Control\n"); - else - printk(KERN_INFO "Disable Tx Flow Control\n"); - if (np->rx_flow) - printk(KERN_INFO "Enable Rx Flow Control\n"); - else - printk(KERN_INFO "Disable Rx Flow Control\n"); - - return 0; -} - -static int -mii_set_media (struct net_device *dev) -{ - __u16 pscr; - __u16 bmcr; - __u16 bmsr; - __u16 anar; - int phy_addr; - struct netdev_private *np; - np = netdev_priv(dev); - phy_addr = np->phy_addr; - - /* Does user set speed? */ - if (np->an_enable) { - /* Advertise capabilities */ - bmsr = mii_read (dev, phy_addr, MII_BMSR); - anar = mii_read (dev, phy_addr, MII_ADVERTISE) & - ~(ADVERTISE_100FULL | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_10HALF | - ADVERTISE_100BASE4); - if (bmsr & BMSR_100FULL) - anar |= ADVERTISE_100FULL; - if (bmsr & BMSR_100HALF) - anar |= ADVERTISE_100HALF; - if (bmsr & BMSR_100BASE4) - anar |= ADVERTISE_100BASE4; - if (bmsr & BMSR_10FULL) - anar |= ADVERTISE_10FULL; - if (bmsr & BMSR_10HALF) - anar |= ADVERTISE_10HALF; - anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - mii_write (dev, phy_addr, MII_ADVERTISE, anar); - - /* Enable Auto crossover */ - pscr = mii_read (dev, phy_addr, MII_PHY_SCR); - pscr |= 3 << 5; /* 11'b */ - mii_write (dev, phy_addr, MII_PHY_SCR, pscr); - - /* Soft reset PHY */ - mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET); - bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET; - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay(1); - } else { - /* Force speed setting */ - /* 1) Disable Auto crossover */ - pscr = mii_read (dev, phy_addr, MII_PHY_SCR); - pscr &= ~(3 << 5); - mii_write (dev, phy_addr, MII_PHY_SCR, pscr); - - /* 2) PHY Reset */ - bmcr = mii_read (dev, phy_addr, MII_BMCR); - bmcr |= BMCR_RESET; - mii_write (dev, phy_addr, MII_BMCR, bmcr); - - /* 3) Power Down */ - bmcr = 0x1940; /* must be 0x1940 */ - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay (100); /* wait a certain time */ - - /* 4) Advertise nothing */ - mii_write (dev, phy_addr, MII_ADVERTISE, 0); - - /* 5) Set media and Power Up */ - bmcr = BMCR_PDOWN; - if (np->speed == 100) { - bmcr |= BMCR_SPEED100; - printk (KERN_INFO "Manual 100 Mbps, "); - } else if (np->speed == 10) { - printk (KERN_INFO "Manual 10 Mbps, "); - } - if (np->full_duplex) { - bmcr |= BMCR_FULLDPLX; - printk (KERN_CONT "Full duplex\n"); - } else { - printk (KERN_CONT "Half duplex\n"); - } -#if 0 - /* Set 1000BaseT Master/Slave setting */ - mscr = mii_read (dev, phy_addr, MII_CTRL1000); - mscr |= MII_MSCR_CFG_ENABLE; - mscr &= ~MII_MSCR_CFG_VALUE = 0; -#endif - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay(10); - } - return 0; -} - -static int -mii_get_media_pcs (struct net_device *dev) -{ - __u16 negotiate; - __u16 bmsr; - int phy_addr; - struct netdev_private *np; - - np = netdev_priv(dev); - phy_addr = np->phy_addr; - - bmsr = mii_read (dev, phy_addr, PCS_BMSR); - if (np->an_enable) { - if (!(bmsr & BMSR_ANEGCOMPLETE)) { - /* Auto-Negotiation not completed */ - return -1; - } - negotiate = mii_read (dev, phy_addr, PCS_ANAR) & - mii_read (dev, phy_addr, PCS_ANLPAR); - np->speed = 1000; - if (negotiate & PCS_ANAR_FULL_DUPLEX) { - printk (KERN_INFO "Auto 1000 Mbps, Full duplex\n"); - np->full_duplex = 1; - } else { - printk (KERN_INFO "Auto 1000 Mbps, half duplex\n"); - np->full_duplex = 0; - } - if (negotiate & PCS_ANAR_PAUSE) { - np->tx_flow &= 1; - np->rx_flow &= 1; - } else if (negotiate & PCS_ANAR_ASYMMETRIC) { - np->tx_flow = 0; - np->rx_flow &= 1; - } - /* else tx_flow, rx_flow = user select */ - } else { - __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR); - printk (KERN_INFO "Operating at 1000 Mbps, "); - if (bmcr & BMCR_FULLDPLX) { - printk (KERN_CONT "Full duplex\n"); - } else { - printk (KERN_CONT "Half duplex\n"); - } - } - if (np->tx_flow) - printk(KERN_INFO "Enable Tx Flow Control\n"); - else - printk(KERN_INFO "Disable Tx Flow Control\n"); - if (np->rx_flow) - printk(KERN_INFO "Enable Rx Flow Control\n"); - else - printk(KERN_INFO "Disable Rx Flow Control\n"); - - return 0; -} - -static int -mii_set_media_pcs (struct net_device *dev) -{ - __u16 bmcr; - __u16 esr; - __u16 anar; - int phy_addr; - struct netdev_private *np; - np = netdev_priv(dev); - phy_addr = np->phy_addr; - - /* Auto-Negotiation? */ - if (np->an_enable) { - /* Advertise capabilities */ - esr = mii_read (dev, phy_addr, PCS_ESR); - anar = mii_read (dev, phy_addr, MII_ADVERTISE) & - ~PCS_ANAR_HALF_DUPLEX & - ~PCS_ANAR_FULL_DUPLEX; - if (esr & (MII_ESR_1000BT_HD | MII_ESR_1000BX_HD)) - anar |= PCS_ANAR_HALF_DUPLEX; - if (esr & (MII_ESR_1000BT_FD | MII_ESR_1000BX_FD)) - anar |= PCS_ANAR_FULL_DUPLEX; - anar |= PCS_ANAR_PAUSE | PCS_ANAR_ASYMMETRIC; - mii_write (dev, phy_addr, MII_ADVERTISE, anar); - - /* Soft reset PHY */ - mii_write (dev, phy_addr, MII_BMCR, BMCR_RESET); - bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET; - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay(1); - } else { - /* Force speed setting */ - /* PHY Reset */ - bmcr = BMCR_RESET; - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay(10); - if (np->full_duplex) { - bmcr = BMCR_FULLDPLX; - printk (KERN_INFO "Manual full duplex\n"); - } else { - bmcr = 0; - printk (KERN_INFO "Manual half duplex\n"); - } - mii_write (dev, phy_addr, MII_BMCR, bmcr); - mdelay(10); - - /* Advertise nothing */ - mii_write (dev, phy_addr, MII_ADVERTISE, 0); - } - return 0; -} - - -static int -rio_close (struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct netdev_private *np = netdev_priv(dev); - struct sk_buff *skb; - int i; - - netif_stop_queue (dev); - - /* Disable interrupts */ - writew (0, ioaddr + IntEnable); - - /* Stop Tx and Rx logics */ - writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl); - - free_irq (dev->irq, dev); - del_timer_sync (&np->timer); - - /* Free all the skbuffs in the queue. */ - for (i = 0; i < RX_RING_SIZE; i++) { - skb = np->rx_skbuff[i]; - if (skb) { - pci_unmap_single(np->pdev, - desc_to_dma(&np->rx_ring[i]), - skb->len, PCI_DMA_FROMDEVICE); - dev_kfree_skb (skb); - np->rx_skbuff[i] = NULL; - } - np->rx_ring[i].status = 0; - np->rx_ring[i].fraginfo = 0; - } - for (i = 0; i < TX_RING_SIZE; i++) { - skb = np->tx_skbuff[i]; - if (skb) { - pci_unmap_single(np->pdev, - desc_to_dma(&np->tx_ring[i]), - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb (skb); - np->tx_skbuff[i] = NULL; - } - } - - return 0; -} - -static void __devexit -rio_remove1 (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata (pdev); - - if (dev) { - struct netdev_private *np = netdev_priv(dev); - - unregister_netdev (dev); - pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, - np->rx_ring_dma); - pci_free_consistent (pdev, TX_TOTAL_SIZE, np->tx_ring, - np->tx_ring_dma); -#ifdef MEM_MAPPING - iounmap ((char *) (dev->base_addr)); -#endif - free_netdev (dev); - pci_release_regions (pdev); - pci_disable_device (pdev); - } - pci_set_drvdata (pdev, NULL); -} - -static struct pci_driver rio_driver = { - .name = "dl2k", - .id_table = rio_pci_tbl, - .probe = rio_probe1, - .remove = __devexit_p(rio_remove1), -}; - -static int __init -rio_init (void) -{ - return pci_register_driver(&rio_driver); -} - -static void __exit -rio_exit (void) -{ - pci_unregister_driver (&rio_driver); -} - -module_init (rio_init); -module_exit (rio_exit); - -/* - -Compile command: - -gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c - -Read Documentation/networking/dl2k.txt for details. - -*/ - diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.h b/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.h deleted file mode 100644 index 30c2da3d..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/dl2k.h +++ /dev/null @@ -1,441 +0,0 @@ -/* D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */ -/* - Copyright (c) 2001, 2002 by D-Link Corporation - Written by Edward Peng.<edward_peng@dlink.com.tw> - Created 03-May-2001, base on Linux' sundance.c. - - 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. -*/ - -#ifndef __DL2K_H__ -#define __DL2K_H__ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/init.h> -#include <linux/crc32.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/bitops.h> -#include <asm/processor.h> /* Processor type for cache alignment. */ -#include <asm/io.h> -#include <asm/uaccess.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/time.h> -#define TX_RING_SIZE 256 -#define TX_QUEUE_LEN (TX_RING_SIZE - 1) /* Limit ring entries actually used.*/ -#define RX_RING_SIZE 256 -#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct netdev_desc) -#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct netdev_desc) - -/* This driver was written to use PCI memory space, however x86-oriented - hardware often uses I/O space accesses. */ -#ifndef MEM_MAPPING -#undef readb -#undef readw -#undef readl -#undef writeb -#undef writew -#undef writel -#define readb inb -#define readw inw -#define readl inl -#define writeb outb -#define writew outw -#define writel outl -#endif - -/* Offsets to the device registers. - Unlike software-only systems, device drivers interact with complex hardware. - It's not useful to define symbolic names for every register bit in the - device. The name can only partially document the semantics and make - the driver longer and more difficult to read. - In general, only the important configuration values or bits changed - multiple times should be defined symbolically. -*/ -enum dl2x_offsets { - /* I/O register offsets */ - DMACtrl = 0x00, - RxDMAStatus = 0x08, - TFDListPtr0 = 0x10, - TFDListPtr1 = 0x14, - TxDMABurstThresh = 0x18, - TxDMAUrgentThresh = 0x19, - TxDMAPollPeriod = 0x1a, - RFDListPtr0 = 0x1c, - RFDListPtr1 = 0x20, - RxDMABurstThresh = 0x24, - RxDMAUrgentThresh = 0x25, - RxDMAPollPeriod = 0x26, - RxDMAIntCtrl = 0x28, - DebugCtrl = 0x2c, - ASICCtrl = 0x30, - FifoCtrl = 0x38, - RxEarlyThresh = 0x3a, - FlowOffThresh = 0x3c, - FlowOnThresh = 0x3e, - TxStartThresh = 0x44, - EepromData = 0x48, - EepromCtrl = 0x4a, - ExpromAddr = 0x4c, - Exprodata = 0x50, - WakeEvent = 0x51, - CountDown = 0x54, - IntStatusAck = 0x5a, - IntEnable = 0x5c, - IntStatus = 0x5e, - TxStatus = 0x60, - MACCtrl = 0x6c, - VLANTag = 0x70, - PhyCtrl = 0x76, - StationAddr0 = 0x78, - StationAddr1 = 0x7a, - StationAddr2 = 0x7c, - VLANId = 0x80, - MaxFrameSize = 0x86, - ReceiveMode = 0x88, - HashTable0 = 0x8c, - HashTable1 = 0x90, - RmonStatMask = 0x98, - StatMask = 0x9c, - RxJumboFrames = 0xbc, - TCPCheckSumErrors = 0xc0, - IPCheckSumErrors = 0xc2, - UDPCheckSumErrors = 0xc4, - TxJumboFrames = 0xf4, - /* Ethernet MIB statistic register offsets */ - OctetRcvOk = 0xa8, - McstOctetRcvOk = 0xac, - BcstOctetRcvOk = 0xb0, - FramesRcvOk = 0xb4, - McstFramesRcvdOk = 0xb8, - BcstFramesRcvdOk = 0xbe, - MacControlFramesRcvd = 0xc6, - FrameTooLongErrors = 0xc8, - InRangeLengthErrors = 0xca, - FramesCheckSeqErrors = 0xcc, - FramesLostRxErrors = 0xce, - OctetXmtOk = 0xd0, - McstOctetXmtOk = 0xd4, - BcstOctetXmtOk = 0xd8, - FramesXmtOk = 0xdc, - McstFramesXmtdOk = 0xe0, - FramesWDeferredXmt = 0xe4, - LateCollisions = 0xe8, - MultiColFrames = 0xec, - SingleColFrames = 0xf0, - BcstFramesXmtdOk = 0xf6, - CarrierSenseErrors = 0xf8, - MacControlFramesXmtd = 0xfa, - FramesAbortXSColls = 0xfc, - FramesWEXDeferal = 0xfe, - /* RMON statistic register offsets */ - EtherStatsCollisions = 0x100, - EtherStatsOctetsTransmit = 0x104, - EtherStatsPktsTransmit = 0x108, - EtherStatsPkts64OctetTransmit = 0x10c, - EtherStats65to127OctetsTransmit = 0x110, - EtherStatsPkts128to255OctetsTransmit = 0x114, - EtherStatsPkts256to511OctetsTransmit = 0x118, - EtherStatsPkts512to1023OctetsTransmit = 0x11c, - EtherStatsPkts1024to1518OctetsTransmit = 0x120, - EtherStatsCRCAlignErrors = 0x124, - EtherStatsUndersizePkts = 0x128, - EtherStatsFragments = 0x12c, - EtherStatsJabbers = 0x130, - EtherStatsOctets = 0x134, - EtherStatsPkts = 0x138, - EtherStats64Octets = 0x13c, - EtherStatsPkts65to127Octets = 0x140, - EtherStatsPkts128to255Octets = 0x144, - EtherStatsPkts256to511Octets = 0x148, - EtherStatsPkts512to1023Octets = 0x14c, - EtherStatsPkts1024to1518Octets = 0x150, -}; - -/* Bits in the interrupt status/mask registers. */ -enum IntStatus_bits { - InterruptStatus = 0x0001, - HostError = 0x0002, - MACCtrlFrame = 0x0008, - TxComplete = 0x0004, - RxComplete = 0x0010, - RxEarly = 0x0020, - IntRequested = 0x0040, - UpdateStats = 0x0080, - LinkEvent = 0x0100, - TxDMAComplete = 0x0200, - RxDMAComplete = 0x0400, - RFDListEnd = 0x0800, - RxDMAPriority = 0x1000, -}; - -/* Bits in the ReceiveMode register. */ -enum ReceiveMode_bits { - ReceiveUnicast = 0x0001, - ReceiveMulticast = 0x0002, - ReceiveBroadcast = 0x0004, - ReceiveAllFrames = 0x0008, - ReceiveMulticastHash = 0x0010, - ReceiveIPMulticast = 0x0020, - ReceiveVLANMatch = 0x0100, - ReceiveVLANHash = 0x0200, -}; -/* Bits in MACCtrl. */ -enum MACCtrl_bits { - DuplexSelect = 0x20, - TxFlowControlEnable = 0x80, - RxFlowControlEnable = 0x0100, - RcvFCS = 0x200, - AutoVLANtagging = 0x1000, - AutoVLANuntagging = 0x2000, - StatsEnable = 0x00200000, - StatsDisable = 0x00400000, - StatsEnabled = 0x00800000, - TxEnable = 0x01000000, - TxDisable = 0x02000000, - TxEnabled = 0x04000000, - RxEnable = 0x08000000, - RxDisable = 0x10000000, - RxEnabled = 0x20000000, -}; - -enum ASICCtrl_LoWord_bits { - PhyMedia = 0x0080, -}; - -enum ASICCtrl_HiWord_bits { - GlobalReset = 0x0001, - RxReset = 0x0002, - TxReset = 0x0004, - DMAReset = 0x0008, - FIFOReset = 0x0010, - NetworkReset = 0x0020, - HostReset = 0x0040, - ResetBusy = 0x0400, -}; - -/* Transmit Frame Control bits */ -enum TFC_bits { - DwordAlign = 0x00000000, - WordAlignDisable = 0x00030000, - WordAlign = 0x00020000, - TCPChecksumEnable = 0x00040000, - UDPChecksumEnable = 0x00080000, - IPChecksumEnable = 0x00100000, - FCSAppendDisable = 0x00200000, - TxIndicate = 0x00400000, - TxDMAIndicate = 0x00800000, - FragCountShift = 24, - VLANTagInsert = 0x0000000010000000, - TFDDone = 0x80000000, - VIDShift = 32, - UsePriorityShift = 48, -}; - -/* Receive Frames Status bits */ -enum RFS_bits { - RxFIFOOverrun = 0x00010000, - RxRuntFrame = 0x00020000, - RxAlignmentError = 0x00040000, - RxFCSError = 0x00080000, - RxOverSizedFrame = 0x00100000, - RxLengthError = 0x00200000, - VLANDetected = 0x00400000, - TCPDetected = 0x00800000, - TCPError = 0x01000000, - UDPDetected = 0x02000000, - UDPError = 0x04000000, - IPDetected = 0x08000000, - IPError = 0x10000000, - FrameStart = 0x20000000, - FrameEnd = 0x40000000, - RFDDone = 0x80000000, - TCIShift = 32, - RFS_Errors = 0x003f0000, -}; - -#define MII_RESET_TIME_OUT 10000 -/* MII register */ -enum _mii_reg { - MII_PHY_SCR = 16, -}; - -/* PCS register */ -enum _pcs_reg { - PCS_BMCR = 0, - PCS_BMSR = 1, - PCS_ANAR = 4, - PCS_ANLPAR = 5, - PCS_ANER = 6, - PCS_ANNPT = 7, - PCS_ANLPRNP = 8, - PCS_ESR = 15, -}; - -/* IEEE Extened Status Register */ -enum _mii_esr { - MII_ESR_1000BX_FD = 0x8000, - MII_ESR_1000BX_HD = 0x4000, - MII_ESR_1000BT_FD = 0x2000, - MII_ESR_1000BT_HD = 0x1000, -}; -/* PHY Specific Control Register */ -#if 0 -typedef union t_MII_PHY_SCR { - u16 image; - struct { - u16 disable_jabber:1; // bit 0 - u16 polarity_reversal:1; // bit 1 - u16 SEQ_test:1; // bit 2 - u16 _bit_3:1; // bit 3 - u16 disable_CLK125:1; // bit 4 - u16 mdi_crossover_mode:2; // bit 6:5 - u16 enable_ext_dist:1; // bit 7 - u16 _bit_8_9:2; // bit 9:8 - u16 force_link:1; // bit 10 - u16 assert_CRS:1; // bit 11 - u16 rcv_fifo_depth:2; // bit 13:12 - u16 xmit_fifo_depth:2; // bit 15:14 - } bits; -} PHY_SCR_t, *PPHY_SCR_t; -#endif - -typedef enum t_MII_ADMIN_STATUS { - adm_reset, - adm_operational, - adm_loopback, - adm_power_down, - adm_isolate -} MII_ADMIN_t, *PMII_ADMIN_t; - -/* Physical Coding Sublayer Management (PCS) */ -/* PCS control and status registers bitmap as the same as MII */ -/* PCS Extended Status register bitmap as the same as MII */ -/* PCS ANAR */ -enum _pcs_anar { - PCS_ANAR_NEXT_PAGE = 0x8000, - PCS_ANAR_REMOTE_FAULT = 0x3000, - PCS_ANAR_ASYMMETRIC = 0x0100, - PCS_ANAR_PAUSE = 0x0080, - PCS_ANAR_HALF_DUPLEX = 0x0040, - PCS_ANAR_FULL_DUPLEX = 0x0020, -}; -/* PCS ANLPAR */ -enum _pcs_anlpar { - PCS_ANLPAR_NEXT_PAGE = PCS_ANAR_NEXT_PAGE, - PCS_ANLPAR_REMOTE_FAULT = PCS_ANAR_REMOTE_FAULT, - PCS_ANLPAR_ASYMMETRIC = PCS_ANAR_ASYMMETRIC, - PCS_ANLPAR_PAUSE = PCS_ANAR_PAUSE, - PCS_ANLPAR_HALF_DUPLEX = PCS_ANAR_HALF_DUPLEX, - PCS_ANLPAR_FULL_DUPLEX = PCS_ANAR_FULL_DUPLEX, -}; - -typedef struct t_SROM { - u16 config_param; /* 0x00 */ - u16 asic_ctrl; /* 0x02 */ - u16 sub_vendor_id; /* 0x04 */ - u16 sub_system_id; /* 0x06 */ - u16 reserved1[12]; /* 0x08-0x1f */ - u8 mac_addr[6]; /* 0x20-0x25 */ - u8 reserved2[10]; /* 0x26-0x2f */ - u8 sib[204]; /* 0x30-0xfb */ - u32 crc; /* 0xfc-0xff */ -} SROM_t, *PSROM_t; - -/* Ioctl custom data */ -struct ioctl_data { - char signature[10]; - int cmd; - int len; - char *data; -}; - -/* The Rx and Tx buffer descriptors. */ -struct netdev_desc { - __le64 next_desc; - __le64 status; - __le64 fraginfo; -}; - -#define PRIV_ALIGN 15 /* Required alignment mask */ -/* Use __attribute__((aligned (L1_CACHE_BYTES))) to maintain alignment - within the structure. */ -struct netdev_private { - /* Descriptor rings first for alignment. */ - struct netdev_desc *rx_ring; - struct netdev_desc *tx_ring; - struct sk_buff *rx_skbuff[RX_RING_SIZE]; - struct sk_buff *tx_skbuff[TX_RING_SIZE]; - dma_addr_t tx_ring_dma; - dma_addr_t rx_ring_dma; - struct pci_dev *pdev; - spinlock_t tx_lock; - spinlock_t rx_lock; - struct net_device_stats stats; - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - unsigned int speed; /* Operating speed */ - unsigned int vlan; /* VLAN Id */ - unsigned int chip_id; /* PCI table chip id */ - unsigned int rx_coalesce; /* Maximum frames each RxDMAComplete intr */ - unsigned int rx_timeout; /* Wait time between RxDMAComplete intr */ - unsigned int tx_coalesce; /* Maximum frames each tx interrupt */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int an_enable:2; /* Auto-Negotiated Enable */ - unsigned int jumbo:1; /* Jumbo frame enable */ - unsigned int coalesce:1; /* Rx coalescing enable */ - unsigned int tx_flow:1; /* Tx flow control enable */ - unsigned int rx_flow:1; /* Rx flow control enable */ - unsigned int phy_media:1; /* 1: fiber, 0: copper */ - unsigned int link_status:1; /* Current link status */ - struct netdev_desc *last_tx; /* Last Tx descriptor used. */ - unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */ - unsigned long cur_tx, old_tx; - struct timer_list timer; - int wake_polarity; - char name[256]; /* net device description */ - u8 duplex_polarity; - u16 mcast_filter[4]; - u16 advertising; /* NWay media advertisement */ - u16 negotiate; /* Negotiated media */ - int phy_addr; /* PHY addresses. */ -}; - -/* The station address location in the EEPROM. */ -/* The struct pci_device_id consist of: - vendor, device Vendor and device ID to match (or PCI_ANY_ID) - subvendor, subdevice Subsystem vendor and device ID to match (or PCI_ANY_ID) - class Device class to match. The class_mask tells which bits - class_mask of the class are honored during the comparison. - driver_data Data private to the driver. -*/ - -static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = { - {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, - {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, - { } -}; -MODULE_DEVICE_TABLE (pci, rio_pci_tbl); -#define TX_TIMEOUT (4*HZ) -#define PACKET_SIZE 1536 -#define MAX_JUMBO 8000 -#define RIO_IO_SIZE 340 -#define DEFAULT_RXC 5 -#define DEFAULT_RXT 750 -#define DEFAULT_TXC 1 -#define MAX_TXC 8 -#endif /* __DL2K_H__ */ diff --git a/ANDROID_3.4.5/drivers/net/ethernet/dlink/sundance.c b/ANDROID_3.4.5/drivers/net/ethernet/dlink/sundance.c deleted file mode 100644 index d783f4f9..00000000 --- a/ANDROID_3.4.5/drivers/net/ethernet/dlink/sundance.c +++ /dev/null @@ -1,1939 +0,0 @@ -/* sundance.c: A Linux device driver for the Sundance ST201 "Alta". */ -/* - Written 1999-2000 by Donald Becker. - - This software may be used and distributed according to the terms of - the GNU General Public License (GPL), incorporated herein by reference. - Drivers based on or derived from this code fall under the GPL and must - retain the authorship, copyright and license notice. This file is not - a complete program and may only be used when the entire operating - system is licensed under the GPL. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Support and updates available at - http://www.scyld.com/network/sundance.html - [link no longer provides useful info -jgarzik] - Archives of the mailing list are still available at - http://www.beowulf.org/pipermail/netdrivers/ - -*/ - -#define DRV_NAME "sundance" -#define DRV_VERSION "1.2" -#define DRV_RELDATE "11-Sep-2006" - - -/* The user-configurable values. - These may be modified when a driver module is loaded.*/ -static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum number of multicast addresses to filter (vs. rx-all-multicast). - Typical is a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -/* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1518 effectively disables this feature. - This chip can receive into offset buffers, so the Alpha does not - need a copy-align. */ -static int rx_copybreak; -static int flowctrl=1; - -/* media[] specifies the media type the NIC operates at. - autosense Autosensing active media. - 10mbps_hd 10Mbps half duplex. - 10mbps_fd 10Mbps full duplex. - 100mbps_hd 100Mbps half duplex. - 100mbps_fd 100Mbps full duplex. - 0 Autosensing active media. - 1 10Mbps half duplex. - 2 10Mbps full duplex. - 3 100Mbps half duplex. - 4 100Mbps full duplex. -*/ -#define MAX_UNITS 8 -static char *media[MAX_UNITS]; - - -/* Operational parameters that are set at compile time. */ - -/* Keep the ring sizes a power of two for compile efficiency. - The compiler will convert <unsigned>'%'<2^N> into a bit mask. - Making the Tx ring too large decreases the effectiveness of channel - bonding and packet priority, and more than 128 requires modifying the - Tx error recovery. - Large receive rings merely waste memory. */ -#define TX_RING_SIZE 32 -#define TX_QUEUE_LEN (TX_RING_SIZE - 1) /* Limit ring entries actually used. */ -#define RX_RING_SIZE 64 -#define RX_BUDGET 32 -#define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct netdev_desc) -#define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct netdev_desc) - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (4*HZ) -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - -/* Include files, designed to support most kernel versions 2.0.0 and later. */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/init.h> -#include <linux/bitops.h> -#include <asm/uaccess.h> -#include <asm/processor.h> /* Processor type for cache alignment. */ -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/dma-mapping.h> -#include <linux/crc32.h> -#include <linux/ethtool.h> -#include <linux/mii.h> - -/* These identify the driver base version and may not be removed. */ -static const char version[] __devinitconst = - KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE - " Written by Donald Becker\n"; - -MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); -MODULE_DESCRIPTION("Sundance Alta Ethernet driver"); -MODULE_LICENSE("GPL"); - -module_param(debug, int, 0); -module_param(rx_copybreak, int, 0); -module_param_array(media, charp, NULL, 0); -module_param(flowctrl, int, 0); -MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)"); -MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames"); -MODULE_PARM_DESC(flowctrl, "Sundance Alta flow control [0|1]"); - -/* - Theory of Operation - -I. Board Compatibility - -This driver is designed for the Sundance Technologies "Alta" ST201 chip. - -II. Board-specific settings - -III. Driver operation - -IIIa. Ring buffers - -This driver uses two statically allocated fixed-size descriptor lists -formed into rings by a branch from the final descriptor to the beginning of -the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. -Some chips explicitly use only 2^N sized rings, while others use a -'next descriptor' pointer that the driver forms into rings. - -IIIb/c. Transmit/Receive Structure - -This driver uses a zero-copy receive and transmit scheme. -The driver allocates full frame size skbuffs for the Rx ring buffers at -open() time and passes the skb->data field to the chip as receive data -buffers. When an incoming frame is less than RX_COPYBREAK bytes long, -a fresh skbuff is allocated and the frame is copied to the new skbuff. -When the incoming frame is larger, the skbuff is passed directly up the -protocol stack. Buffers consumed this way are replaced by newly allocated -skbuffs in a later phase of receives. - -The RX_COPYBREAK value is chosen to trade-off the memory wasted by -using a full-sized skbuff for small frames vs. the copying costs of larger -frames. New boards are typically used in generously configured machines -and the underfilled buffers have negligible impact compared to the benefit of -a single allocation size, so the default value of zero results in never -copying packets. When copying is done, the cost is usually mitigated by using -a combined copy/checksum routine. Copying also preloads the cache, which is -most useful with small frames. - -A subtle aspect of the operation is that the IP header at offset 14 in an -ethernet frame isn't longword aligned for further processing. -Unaligned buffers are permitted by the Sundance hardware, so -frames are received into the skbuff at an offset of "+2", 16-byte aligning -the IP header. - -IIId. Synchronization - -The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single -threaded by the hardware and interrupt handling software. - -The send packet thread has partial control over the Tx ring and 'dev->tbusy' -flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next -queue slot is empty, it clears the tbusy flag when finished otherwise it sets -the 'lp->tx_full' flag. - -The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. After reaping the stats, it marks the Tx queue entry as -empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it -clears both the tx_full and tbusy flags. - -IV. Notes - -IVb. References - -The Sundance ST201 datasheet, preliminary version. -The Kendin KS8723 datasheet, preliminary version. -The ICplus IP100 datasheet, preliminary version. -http://www.scyld.com/expert/100mbps.html -http://www.scyld.com/expert/NWay.html - -IVc. Errata - -*/ - -/* Work-around for Kendin chip bugs. */ -#ifndef CONFIG_SUNDANCE_MMIO -#define USE_IO_OPS 1 -#endif - -static DEFINE_PCI_DEVICE_TABLE(sundance_pci_tbl) = { - { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 }, - { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 }, - { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 }, - { 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 }, - { 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, - { } -}; -MODULE_DEVICE_TABLE(pci, sundance_pci_tbl); - -enum { - netdev_io_size = 128 -}; - -struct pci_id_info { - const char *name; -}; -static const struct pci_id_info pci_id_tbl[] __devinitdata = { - {"D-Link DFE-550TX FAST Ethernet Adapter"}, - {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, - {"D-Link DFE-580TX 4 port Server Adapter"}, - {"D-Link DFE-530TXS FAST Ethernet Adapter"}, - {"D-Link DL10050-based FAST Ethernet Adapter"}, - {"Sundance Technology Alta"}, - {"IC Plus Corporation IP100A FAST Ethernet Adapter"}, - { } /* terminate list. */ -}; - -/* This driver was written to use PCI memory space, however x86-oriented - hardware often uses I/O space accesses. */ - -/* Offsets to the device registers. - Unlike software-only systems, device drivers interact with complex hardware. - It's not useful to define symbolic names for every register bit in the - device. The name can only partially document the semantics and make - the driver longer and more difficult to read. - In general, only the important configuration values or bits changed - multiple times should be defined symbolically. -*/ -enum alta_offsets { - DMACtrl = 0x00, - TxListPtr = 0x04, - TxDMABurstThresh = 0x08, - TxDMAUrgentThresh = 0x09, - TxDMAPollPeriod = 0x0a, - RxDMAStatus = 0x0c, - RxListPtr = 0x10, - DebugCtrl0 = 0x1a, - DebugCtrl1 = 0x1c, - RxDMABurstThresh = 0x14, - RxDMAUrgentThresh = 0x15, - RxDMAPollPeriod = 0x16, - LEDCtrl = 0x1a, - ASICCtrl = 0x30, - EEData = 0x34, - EECtrl = 0x36, - FlashAddr = 0x40, - FlashData = 0x44, - TxStatus = 0x46, - TxFrameId = 0x47, - DownCounter = 0x18, - IntrClear = 0x4a, - IntrEnable = 0x4c, - IntrStatus = 0x4e, - MACCtrl0 = 0x50, - MACCtrl1 = 0x52, - StationAddr = 0x54, - MaxFrameSize = 0x5A, - RxMode = 0x5c, - MIICtrl = 0x5e, - MulticastFilter0 = 0x60, - MulticastFilter1 = 0x64, - RxOctetsLow = 0x68, - RxOctetsHigh = 0x6a, - TxOctetsLow = 0x6c, - TxOctetsHigh = 0x6e, - TxFramesOK = 0x70, - RxFramesOK = 0x72, - StatsCarrierError = 0x74, - StatsLateColl = 0x75, - StatsMultiColl = 0x76, - StatsOneColl = 0x77, - StatsTxDefer = 0x78, - RxMissed = 0x79, - StatsTxXSDefer = 0x7a, - StatsTxAbort = 0x7b, - StatsBcastTx = 0x7c, - StatsBcastRx = 0x7d, - StatsMcastTx = 0x7e, - StatsMcastRx = 0x7f, - /* Aliased and bogus values! */ - RxStatus = 0x0c, -}; - -#define ASIC_HI_WORD(x) ((x) + 2) - -enum ASICCtrl_HiWord_bit { - GlobalReset = 0x0001, - RxReset = 0x0002, - TxReset = 0x0004, - DMAReset = 0x0008, - FIFOReset = 0x0010, - NetworkReset = 0x0020, - HostReset = 0x0040, - ResetBusy = 0x0400, -}; - -/* Bits in the interrupt status/mask registers. */ -enum intr_status_bits { - IntrSummary=0x0001, IntrPCIErr=0x0002, IntrMACCtrl=0x0008, - IntrTxDone=0x0004, IntrRxDone=0x0010, IntrRxStart=0x0020, - IntrDrvRqst=0x0040, - StatsMax=0x0080, LinkChange=0x0100, - IntrTxDMADone=0x0200, IntrRxDMADone=0x0400, -}; - -/* Bits in the RxMode register. */ -enum rx_mode_bits { - AcceptAllIPMulti=0x20, AcceptMultiHash=0x10, AcceptAll=0x08, - AcceptBroadcast=0x04, AcceptMulticast=0x02, AcceptMyPhys=0x01, -}; -/* Bits in MACCtrl. */ -enum mac_ctrl0_bits { - EnbFullDuplex=0x20, EnbRcvLargeFrame=0x40, - EnbFlowCtrl=0x100, EnbPassRxCRC=0x200, -}; -enum mac_ctrl1_bits { - StatsEnable=0x0020, StatsDisable=0x0040, StatsEnabled=0x0080, - TxEnable=0x0100, TxDisable=0x0200, TxEnabled=0x0400, - RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000, -}; - -/* The Rx and Tx buffer descriptors. */ -/* Note that using only 32 bit fields simplifies conversion to big-endian - architectures. */ -struct netdev_desc { - __le32 next_desc; - __le32 status; - struct desc_frag { __le32 addr, length; } frag[1]; -}; - -/* Bits in netdev_desc.status */ -enum desc_status_bits { - DescOwn=0x8000, - DescEndPacket=0x4000, - DescEndRing=0x2000, - LastFrag=0x80000000, - DescIntrOnTx=0x8000, - DescIntrOnDMADone=0x80000000, - DisableAlign = 0x00000001, -}; - -#define PRIV_ALIGN 15 /* Required alignment mask */ -/* Use __attribute__((aligned (L1_CACHE_BYTES))) to maintain alignment - within the structure. */ -#define MII_CNT 4 -struct netdev_private { - /* Descriptor rings first for alignment. */ - struct netdev_desc *rx_ring; - struct netdev_desc *tx_ring; - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - dma_addr_t tx_ring_dma; - dma_addr_t rx_ring_dma; - struct timer_list timer; /* Media monitoring timer. */ - /* ethtool extra stats */ - struct { - u64 tx_multiple_collisions; - u64 tx_single_collisions; - u64 tx_late_collisions; - u64 tx_deferred; - u64 tx_deferred_excessive; - u64 tx_aborted; - u64 tx_bcasts; - u64 rx_bcasts; - u64 tx_mcasts; - u64 rx_mcasts; - } xstats; - /* Frequently used values: keep some adjacent for cache effect. */ - spinlock_t lock; - int msg_enable; - int chip_id; - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - struct netdev_desc *last_tx; /* Last Tx descriptor used. */ - unsigned int cur_tx, dirty_tx; - /* These values are keep track of the transceiver/media in use. */ - unsigned int flowctrl:1; - unsigned int default_port:4; /* Last dev->if_port value. */ - unsigned int an_enable:1; - unsigned int speed; - struct tasklet_struct rx_tasklet; - struct tasklet_struct tx_tasklet; - int budget; - int cur_task; - /* Multicast and receive mode. */ - spinlock_t mcastlock; /* SMP lock multicast updates. */ - u16 mcast_filter[4]; - /* MII transceiver section. */ - struct mii_if_info mii_if; - int mii_preamble_required; - unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ - struct pci_dev *pci_dev; - void __iomem *base; - spinlock_t statlock; -}; - -/* The station address location in the EEPROM. */ -#define EEPROM_SA_OFFSET 0x10 -#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \ - IntrDrvRqst | IntrTxDone | StatsMax | \ - LinkChange) - -static int change_mtu(struct net_device *dev, int new_mtu); -static int eeprom_read(void __iomem *ioaddr, int location); -static int mdio_read(struct net_device *dev, int phy_id, int location); -static void mdio_write(struct net_device *dev, int phy_id, int location, int value); -static int mdio_wait_link(struct net_device *dev, int wait); -static int netdev_open(struct net_device *dev); -static void check_duplex(struct net_device *dev); -static void netdev_timer(unsigned long data); -static void tx_timeout(struct net_device *dev); -static void init_ring(struct net_device *dev); -static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev); -static int reset_tx (struct net_device *dev); -static irqreturn_t intr_handler(int irq, void *dev_instance); -static void rx_poll(unsigned long data); -static void tx_poll(unsigned long data); -static void refill_rx (struct net_device *dev); -static void netdev_error(struct net_device *dev, int intr_status); -static void netdev_error(struct net_device *dev, int intr_status); -static void set_rx_mode(struct net_device *dev); -static int __set_mac_addr(struct net_device *dev); -static int sundance_set_mac_addr(struct net_device *dev, void *data); -static struct net_device_stats *get_stats(struct net_device *dev); -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int netdev_close(struct net_device *dev); -static const struct ethtool_ops ethtool_ops; - -static void sundance_reset(struct net_device *dev, unsigned long reset_cmd) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base + ASICCtrl; - int countdown; - - /* ST201 documentation states ASICCtrl is a 32bit register */ - iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr); - /* ST201 documentation states reset can take up to 1 ms */ - countdown = 10 + 1; - while (ioread32 (ioaddr) & (ResetBusy << 16)) { - if (--countdown == 0) { - printk(KERN_WARNING "%s : reset not completed !!\n", dev->name); - break; - } - udelay(100); - } -} - -static const struct net_device_ops netdev_ops = { - .ndo_open = netdev_open, - .ndo_stop = netdev_close, - .ndo_start_xmit = start_tx, - .ndo_get_stats = get_stats, - .ndo_set_rx_mode = set_rx_mode, - .ndo_do_ioctl = netdev_ioctl, - .ndo_tx_timeout = tx_timeout, - .ndo_change_mtu = change_mtu, - .ndo_set_mac_address = sundance_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __devinit sundance_probe1 (struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev; - struct netdev_private *np; - static int card_idx; - int chip_idx = ent->driver_data; - int irq; - int i; - void __iomem *ioaddr; - u16 mii_ctl; - void *ring_space; - dma_addr_t ring_dma; -#ifdef USE_IO_OPS - int bar = 0; -#else - int bar = 1; -#endif - int phy, phy_end, phy_idx = 0; - -/* when built into the kernel, we only print version if device is found */ -#ifndef MODULE - static int printed_version; - if (!printed_version++) - printk(version); -#endif - - if (pci_enable_device(pdev)) - return -EIO; - pci_set_master(pdev); - - irq = pdev->irq; - - dev = alloc_etherdev(sizeof(*np)); - if (!dev) - return -ENOMEM; - SET_NETDEV_DEV(dev, &pdev->dev); - - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_netdev; - - ioaddr = pci_iomap(pdev, bar, netdev_io_size); - if (!ioaddr) - goto err_out_res; - - for (i = 0; i < 3; i++) - ((__le16 *)dev->dev_addr)[i] = - cpu_to_le16(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET)); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - dev->base_addr = (unsigned long)ioaddr; - dev->irq = irq; - - np = netdev_priv(dev); - np->base = ioaddr; - np->pci_dev = pdev; - np->chip_id = chip_idx; - np->msg_enable = (1 << debug) - 1; - spin_lock_init(&np->lock); - spin_lock_init(&np->statlock); - tasklet_init(&np->rx_tasklet, rx_poll, (unsigned long)dev); - tasklet_init(&np->tx_tasklet, tx_poll, (unsigned long)dev); - - ring_space = dma_alloc_coherent(&pdev->dev, TX_TOTAL_SIZE, - &ring_dma, GFP_KERNEL); - if (!ring_space) - goto err_out_cleardev; - np->tx_ring = (struct netdev_desc *)ring_space; - np->tx_ring_dma = ring_dma; - - ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE, - &ring_dma, GFP_KERNEL); - if (!ring_space) - goto err_out_unmap_tx; - np->rx_ring = (struct netdev_desc *)ring_space; - np->rx_ring_dma = ring_dma; - - np->mii_if.dev = dev; - np->mii_if.mdio_read = mdio_read; - np->mii_if.mdio_write = mdio_write; - np->mii_if.phy_id_mask = 0x1f; - np->mii_if.reg_num_mask = 0x1f; - - /* The chip-specific entries in the device structure. */ - dev->netdev_ops = &netdev_ops; - SET_ETHTOOL_OPS(dev, ðtool_ops); - dev->watchdog_timeo = TX_TIMEOUT; - - pci_set_drvdata(pdev, dev); - - i = register_netdev(dev); - if (i) - goto err_out_unmap_rx; - - printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n", - dev->name, pci_id_tbl[chip_idx].name, ioaddr, - dev->dev_addr, irq); - - np->phys[0] = 1; /* Default setting */ - np->mii_preamble_required++; - - /* - * It seems some phys doesn't deal well with address 0 being accessed - * first - */ - if (sundance_pci_tbl[np->chip_id].device == 0x0200) { - phy = 0; - phy_end = 31; - } else { - phy = 1; - phy_end = 32; /* wraps to zero, due to 'phy & 0x1f' */ - } - for (; phy <= phy_end && phy_idx < MII_CNT; phy++) { - int phyx = phy & 0x1f; - int mii_status = mdio_read(dev, phyx, MII_BMSR); - if (mii_status != 0xffff && mii_status != 0x0000) { - np->phys[phy_idx++] = phyx; - np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE); - if ((mii_status & 0x0040) == 0) - np->mii_preamble_required++; - printk(KERN_INFO "%s: MII PHY found at address %d, status " - "0x%4.4x advertising %4.4x.\n", - dev->name, phyx, mii_status, np->mii_if.advertising); - } - } - np->mii_preamble_required--; - - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n", - dev->name, ioread32(ioaddr + ASICCtrl)); - goto err_out_unregister; - } - - np->mii_if.phy_id = np->phys[0]; - - /* Parse override configuration */ - np->an_enable = 1; - if (card_idx < MAX_UNITS) { - if (media[card_idx] != NULL) { - np->an_enable = 0; - if (strcmp (media[card_idx], "100mbps_fd") == 0 || - strcmp (media[card_idx], "4") == 0) { - np->speed = 100; - np->mii_if.full_duplex = 1; - } else if (strcmp (media[card_idx], "100mbps_hd") == 0 || - strcmp (media[card_idx], "3") == 0) { - np->speed = 100; - np->mii_if.full_duplex = 0; - } else if (strcmp (media[card_idx], "10mbps_fd") == 0 || - strcmp (media[card_idx], "2") == 0) { - np->speed = 10; - np->mii_if.full_duplex = 1; - } else if (strcmp (media[card_idx], "10mbps_hd") == 0 || - strcmp (media[card_idx], "1") == 0) { - np->speed = 10; - np->mii_if.full_duplex = 0; - } else { - np->an_enable = 1; - } - } - if (flowctrl == 1) - np->flowctrl = 1; - } - - /* Fibre PHY? */ - if (ioread32 (ioaddr + ASICCtrl) & 0x80) { - /* Default 100Mbps Full */ - if (np->an_enable) { - np->speed = 100; - np->mii_if.full_duplex = 1; - np->an_enable = 0; - } - } - /* Reset PHY */ - mdio_write (dev, np->phys[0], MII_BMCR, BMCR_RESET); - mdelay (300); - /* If flow control enabled, we need to advertise it.*/ - if (np->flowctrl) - mdio_write (dev, np->phys[0], MII_ADVERTISE, np->mii_if.advertising | 0x0400); - mdio_write (dev, np->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART); - /* Force media type */ - if (!np->an_enable) { - mii_ctl = 0; - mii_ctl |= (np->speed == 100) ? BMCR_SPEED100 : 0; - mii_ctl |= (np->mii_if.full_duplex) ? BMCR_FULLDPLX : 0; - mdio_write (dev, np->phys[0], MII_BMCR, mii_ctl); - printk (KERN_INFO "Override speed=%d, %s duplex\n", - np->speed, np->mii_if.full_duplex ? "Full" : "Half"); - - } - - /* Perhaps move the reset here? */ - /* Reset the chip to erase previous misconfiguration. */ - if (netif_msg_hw(np)) - printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl)); - sundance_reset(dev, 0x00ff << 16); - if (netif_msg_hw(np)) - printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl)); - - card_idx++; - return 0; - -err_out_unregister: - unregister_netdev(dev); -err_out_unmap_rx: - dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, - np->rx_ring, np->rx_ring_dma); -err_out_unmap_tx: - dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, - np->tx_ring, np->tx_ring_dma); -err_out_cleardev: - pci_set_drvdata(pdev, NULL); - pci_iounmap(pdev, ioaddr); -err_out_res: - pci_release_regions(pdev); -err_out_netdev: - free_netdev (dev); - return -ENODEV; -} - -static int change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */ - return -EINVAL; - if (netif_running(dev)) - return -EBUSY; - dev->mtu = new_mtu; - return 0; -} - -#define eeprom_delay(ee_addr) ioread32(ee_addr) -/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */ -static int __devinit eeprom_read(void __iomem *ioaddr, int location) -{ - int boguscnt = 10000; /* Typical 1900 ticks. */ - iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl); - do { - eeprom_delay(ioaddr + EECtrl); - if (! (ioread16(ioaddr + EECtrl) & 0x8000)) { - return ioread16(ioaddr + EEData); - } - } while (--boguscnt > 0); - return 0; -} - -/* MII transceiver control section. - Read and write the MII registers using software-generated serial - MDIO protocol. See the MII specifications or DP83840A data sheet - for details. - - The maximum data clock rate is 2.5 Mhz. The minimum timing is usually - met by back-to-back 33Mhz PCI cycles. */ -#define mdio_delay() ioread8(mdio_addr) - -enum mii_reg_bits { - MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004, -}; -#define MDIO_EnbIn (0) -#define MDIO_WRITE0 (MDIO_EnbOutput) -#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput) - -/* Generate the preamble required for initial synchronization and - a few older transceivers. */ -static void mdio_sync(void __iomem *mdio_addr) -{ - int bits = 32; - - /* Establish sync by sending at least 32 logic ones. */ - while (--bits >= 0) { - iowrite8(MDIO_WRITE1, mdio_addr); - mdio_delay(); - iowrite8(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); - mdio_delay(); - } -} - -static int mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *mdio_addr = np->base + MIICtrl; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i, retval = 0; - - if (np->mii_preamble_required) - mdio_sync(mdio_addr); - - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - - iowrite8(dataval, mdio_addr); - mdio_delay(); - iowrite8(dataval | MDIO_ShiftClk, mdio_addr); - mdio_delay(); - } - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - iowrite8(MDIO_EnbIn, mdio_addr); - mdio_delay(); - retval = (retval << 1) | ((ioread8(mdio_addr) & MDIO_Data) ? 1 : 0); - iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); - mdio_delay(); - } - return (retval>>1) & 0xffff; -} - -static void mdio_write(struct net_device *dev, int phy_id, int location, int value) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *mdio_addr = np->base + MIICtrl; - int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; - int i; - - if (np->mii_preamble_required) - mdio_sync(mdio_addr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - - iowrite8(dataval, mdio_addr); - mdio_delay(); - iowrite8(dataval | MDIO_ShiftClk, mdio_addr); - mdio_delay(); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - iowrite8(MDIO_EnbIn, mdio_addr); - mdio_delay(); - iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); - mdio_delay(); - } -} - -static int mdio_wait_link(struct net_device *dev, int wait) -{ - int bmsr; - int phy_id; - struct netdev_private *np; - - np = netdev_priv(dev); - phy_id = np->phys[0]; - - do { - bmsr = mdio_read(dev, phy_id, MII_BMSR); - if (bmsr & 0x0004) - return 0; - mdelay(1); - } while (--wait > 0); - return -1; -} - -static int netdev_open(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - unsigned long flags; - int i; - - /* Do we need to reset the chip??? */ - - i = request_irq(dev->irq, intr_handler, IRQF_SHARED, dev->name, dev); - if (i) - return i; - - if (netif_msg_ifup(np)) - printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", - dev->name, dev->irq); - init_ring(dev); - - iowrite32(np->rx_ring_dma, ioaddr + RxListPtr); - /* The Tx list pointer is written as packets are queued. */ - - /* Initialize other registers. */ - __set_mac_addr(dev); -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - iowrite16(dev->mtu + 18, ioaddr + MaxFrameSize); -#else - iowrite16(dev->mtu + 14, ioaddr + MaxFrameSize); -#endif - if (dev->mtu > 2047) - iowrite32(ioread32(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl); - - /* Configure the PCI bus bursts and FIFO thresholds. */ - - if (dev->if_port == 0) - dev->if_port = np->default_port; - - spin_lock_init(&np->mcastlock); - - set_rx_mode(dev); - iowrite16(0, ioaddr + IntrEnable); - iowrite16(0, ioaddr + DownCounter); - /* Set the chip to poll every N*320nsec. */ - iowrite8(100, ioaddr + RxDMAPollPeriod); - iowrite8(127, ioaddr + TxDMAPollPeriod); - /* Fix DFE-580TX packet drop issue */ - if (np->pci_dev->revision >= 0x14) - iowrite8(0x01, ioaddr + DebugCtrl1); - netif_start_queue(dev); - - spin_lock_irqsave(&np->lock, flags); - reset_tx(dev); - spin_unlock_irqrestore(&np->lock, flags); - - iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); - - if (netif_msg_ifup(np)) - printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " - "MAC Control %x, %4.4x %4.4x.\n", - dev->name, ioread32(ioaddr + RxStatus), ioread8(ioaddr + TxStatus), - ioread32(ioaddr + MACCtrl0), - ioread16(ioaddr + MACCtrl1), ioread16(ioaddr + MACCtrl0)); - - /* Set the timer to check for link beat. */ - init_timer(&np->timer); - np->timer.expires = jiffies + 3*HZ; - np->timer.data = (unsigned long)dev; - np->timer.function = netdev_timer; /* timer handler */ - add_timer(&np->timer); - - /* Enable interrupts by setting the interrupt mask. */ - iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); - - return 0; -} - -static void check_duplex(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); - int negotiated = mii_lpa & np->mii_if.advertising; - int duplex; - - /* Force media */ - if (!np->an_enable || mii_lpa == 0xffff) { - if (np->mii_if.full_duplex) - iowrite16 (ioread16 (ioaddr + MACCtrl0) | EnbFullDuplex, - ioaddr + MACCtrl0); - return; - } - - /* Autonegotiation */ - duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; - if (np->mii_if.full_duplex != duplex) { - np->mii_if.full_duplex = duplex; - if (netif_msg_link(np)) - printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " - "negotiated capability %4.4x.\n", dev->name, - duplex ? "full" : "half", np->phys[0], negotiated); - iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0); - } -} - -static void netdev_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - int next_tick = 10*HZ; - - if (netif_msg_timer(np)) { - printk(KERN_DEBUG "%s: Media selection timer tick, intr status %4.4x, " - "Tx %x Rx %x.\n", - dev->name, ioread16(ioaddr + IntrEnable), - ioread8(ioaddr + TxStatus), ioread32(ioaddr + RxStatus)); - } - check_duplex(dev); - np->timer.expires = jiffies + next_tick; - add_timer(&np->timer); -} - -static void tx_timeout(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - unsigned long flag; - - netif_stop_queue(dev); - tasklet_disable(&np->tx_tasklet); - iowrite16(0, ioaddr + IntrEnable); - printk(KERN_WARNING "%s: Transmit timed out, TxStatus %2.2x " - "TxFrameId %2.2x," - " resetting...\n", dev->name, ioread8(ioaddr + TxStatus), - ioread8(ioaddr + TxFrameId)); - - { - int i; - for (i=0; i<TX_RING_SIZE; i++) { - printk(KERN_DEBUG "%02x %08llx %08x %08x(%02x) %08x %08x\n", i, - (unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)), - le32_to_cpu(np->tx_ring[i].next_desc), - le32_to_cpu(np->tx_ring[i].status), - (le32_to_cpu(np->tx_ring[i].status) >> 2) & 0xff, - le32_to_cpu(np->tx_ring[i].frag[0].addr), - le32_to_cpu(np->tx_ring[i].frag[0].length)); - } - printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n", - ioread32(np->base + TxListPtr), - netif_queue_stopped(dev)); - printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n", - np->cur_tx, np->cur_tx % TX_RING_SIZE, - np->dirty_tx, np->dirty_tx % TX_RING_SIZE); - printk(KERN_DEBUG "cur_rx=%d dirty_rx=%d\n", np->cur_rx, np->dirty_rx); - printk(KERN_DEBUG "cur_task=%d\n", np->cur_task); - } - spin_lock_irqsave(&np->lock, flag); - - /* Stop and restart the chip's Tx processes . */ - reset_tx(dev); - spin_unlock_irqrestore(&np->lock, flag); - - dev->if_port = 0; - - dev->trans_start = jiffies; /* prevent tx timeout */ - dev->stats.tx_errors++; - if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { - netif_wake_queue(dev); - } - iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); - tasklet_enable(&np->tx_tasklet); -} - - -/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void init_ring(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - int i; - - np->cur_rx = np->cur_tx = 0; - np->dirty_rx = np->dirty_tx = 0; - np->cur_task = 0; - - np->rx_buf_sz = (dev->mtu <= 1520 ? PKT_BUF_SZ : dev->mtu + 16); - - /* Initialize all Rx descriptors. */ - for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].next_desc = cpu_to_le32(np->rx_ring_dma + - ((i+1)%RX_RING_SIZE)*sizeof(*np->rx_ring)); - np->rx_ring[i].status = 0; - np->rx_ring[i].frag[0].length = 0; - np->rx_skbuff[i] = NULL; - } - - /* Fill in the Rx buffers. Handle allocation failure gracefully. */ - for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = - netdev_alloc_skb(dev, np->rx_buf_sz + 2); - np->rx_skbuff[i] = skb; - if (skb == NULL) - break; - skb_reserve(skb, 2); /* 16 byte align the IP header. */ - np->rx_ring[i].frag[0].addr = cpu_to_le32( - dma_map_single(&np->pci_dev->dev, skb->data, - np->rx_buf_sz, DMA_FROM_DEVICE)); - if (dma_mapping_error(&np->pci_dev->dev, - np->rx_ring[i].frag[0].addr)) { - dev_kfree_skb(skb); - np->rx_skbuff[i] = NULL; - break; - } - np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag); - } - np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); - - for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = NULL; - np->tx_ring[i].status = 0; - } -} - -static void tx_poll (unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); - unsigned head = np->cur_task % TX_RING_SIZE; - struct netdev_desc *txdesc = - &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE]; - - /* Chain the next pointer */ - for (; np->cur_tx - np->cur_task > 0; np->cur_task++) { - int entry = np->cur_task % TX_RING_SIZE; - txdesc = &np->tx_ring[entry]; - if (np->last_tx) { - np->last_tx->next_desc = cpu_to_le32(np->tx_ring_dma + - entry*sizeof(struct netdev_desc)); - } - np->last_tx = txdesc; - } - /* Indicate the latest descriptor of tx ring */ - txdesc->status |= cpu_to_le32(DescIntrOnTx); - - if (ioread32 (np->base + TxListPtr) == 0) - iowrite32 (np->tx_ring_dma + head * sizeof(struct netdev_desc), - np->base + TxListPtr); -} - -static netdev_tx_t -start_tx (struct sk_buff *skb, struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - struct netdev_desc *txdesc; - unsigned entry; - - /* Calculate the next Tx descriptor entry. */ - entry = np->cur_tx % TX_RING_SIZE; - np->tx_skbuff[entry] = skb; - txdesc = &np->tx_ring[entry]; - - txdesc->next_desc = 0; - txdesc->status = cpu_to_le32 ((entry << 2) | DisableAlign); - txdesc->frag[0].addr = cpu_to_le32(dma_map_single(&np->pci_dev->dev, - skb->data, skb->len, DMA_TO_DEVICE)); - if (dma_mapping_error(&np->pci_dev->dev, - txdesc->frag[0].addr)) - goto drop_frame; - txdesc->frag[0].length = cpu_to_le32 (skb->len | LastFrag); - - /* Increment cur_tx before tasklet_schedule() */ - np->cur_tx++; - mb(); - /* Schedule a tx_poll() task */ - tasklet_schedule(&np->tx_tasklet); - - /* On some architectures: explicitly flush cache lines here. */ - if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1 && - !netif_queue_stopped(dev)) { - /* do nothing */ - } else { - netif_stop_queue (dev); - } - if (netif_msg_tx_queued(np)) { - printk (KERN_DEBUG - "%s: Transmit frame #%d queued in slot %d.\n", - dev->name, np->cur_tx, entry); - } - return NETDEV_TX_OK; - -drop_frame: - dev_kfree_skb(skb); - np->tx_skbuff[entry] = NULL; - dev->stats.tx_dropped++; - return NETDEV_TX_OK; -} - -/* Reset hardware tx and free all of tx buffers */ -static int -reset_tx (struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - struct sk_buff *skb; - int i; - - /* Reset tx logic, TxListPtr will be cleaned */ - iowrite16 (TxDisable, ioaddr + MACCtrl1); - sundance_reset(dev, (NetworkReset|FIFOReset|DMAReset|TxReset) << 16); - - /* free all tx skbuff */ - for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_ring[i].next_desc = 0; - - skb = np->tx_skbuff[i]; - if (skb) { - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(np->tx_ring[i].frag[0].addr), - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - np->tx_skbuff[i] = NULL; - dev->stats.tx_dropped++; - } - } - np->cur_tx = np->dirty_tx = 0; - np->cur_task = 0; - - np->last_tx = NULL; - iowrite8(127, ioaddr + TxDMAPollPeriod); - - iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); - return 0; -} - -/* The interrupt handler cleans up after the Tx thread, - and schedule a Rx thread work */ -static irqreturn_t intr_handler(int irq, void *dev_instance) -{ - struct net_device *dev = (struct net_device *)dev_instance; - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - int hw_frame_id; - int tx_cnt; - int tx_status; - int handled = 0; - int i; - - - do { - int intr_status = ioread16(ioaddr + IntrStatus); - iowrite16(intr_status, ioaddr + IntrStatus); - - if (netif_msg_intr(np)) - printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", - dev->name, intr_status); - - if (!(intr_status & DEFAULT_INTR)) - break; - - handled = 1; - - if (intr_status & (IntrRxDMADone)) { - iowrite16(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), - ioaddr + IntrEnable); - if (np->budget < 0) - np->budget = RX_BUDGET; - tasklet_schedule(&np->rx_tasklet); - } - if (intr_status & (IntrTxDone | IntrDrvRqst)) { - tx_status = ioread16 (ioaddr + TxStatus); - for (tx_cnt=32; tx_status & 0x80; --tx_cnt) { - if (netif_msg_tx_done(np)) - printk - ("%s: Transmit status is %2.2x.\n", - dev->name, tx_status); - if (tx_status & 0x1e) { - if (netif_msg_tx_err(np)) - printk("%s: Transmit error status %4.4x.\n", - dev->name, tx_status); - dev->stats.tx_errors++; - if (tx_status & 0x10) - dev->stats.tx_fifo_errors++; - if (tx_status & 0x08) - dev->stats.collisions++; - if (tx_status & 0x04) - dev->stats.tx_fifo_errors++; - if (tx_status & 0x02) - dev->stats.tx_window_errors++; - - /* - ** This reset has been verified on - ** DFE-580TX boards ! phdm@macqel.be. - */ - if (tx_status & 0x10) { /* TxUnderrun */ - /* Restart Tx FIFO and transmitter */ - sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); - /* No need to reset the Tx pointer here */ - } - /* Restart the Tx. Need to make sure tx enabled */ - i = 10; - do { - iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1); - if (ioread16(ioaddr + MACCtrl1) & TxEnabled) - break; - mdelay(1); - } while (--i); - } - /* Yup, this is a documentation bug. It cost me *hours*. */ - iowrite16 (0, ioaddr + TxStatus); - if (tx_cnt < 0) { - iowrite32(5000, ioaddr + DownCounter); - break; - } - tx_status = ioread16 (ioaddr + TxStatus); - } - hw_frame_id = (tx_status >> 8) & 0xff; - } else { - hw_frame_id = ioread8(ioaddr + TxFrameId); - } - - if (np->pci_dev->revision >= 0x14) { - spin_lock(&np->lock); - for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { - int entry = np->dirty_tx % TX_RING_SIZE; - struct sk_buff *skb; - int sw_frame_id; - sw_frame_id = (le32_to_cpu( - np->tx_ring[entry].status) >> 2) & 0xff; - if (sw_frame_id == hw_frame_id && - !(le32_to_cpu(np->tx_ring[entry].status) - & 0x00010000)) - break; - if (sw_frame_id == (hw_frame_id + 1) % - TX_RING_SIZE) - break; - skb = np->tx_skbuff[entry]; - /* Free the original skb. */ - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(np->tx_ring[entry].frag[0].addr), - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq (np->tx_skbuff[entry]); - np->tx_skbuff[entry] = NULL; - np->tx_ring[entry].frag[0].addr = 0; - np->tx_ring[entry].frag[0].length = 0; - } - spin_unlock(&np->lock); - } else { - spin_lock(&np->lock); - for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { - int entry = np->dirty_tx % TX_RING_SIZE; - struct sk_buff *skb; - if (!(le32_to_cpu(np->tx_ring[entry].status) - & 0x00010000)) - break; - skb = np->tx_skbuff[entry]; - /* Free the original skb. */ - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(np->tx_ring[entry].frag[0].addr), - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq (np->tx_skbuff[entry]); - np->tx_skbuff[entry] = NULL; - np->tx_ring[entry].frag[0].addr = 0; - np->tx_ring[entry].frag[0].length = 0; - } - spin_unlock(&np->lock); - } - - if (netif_queue_stopped(dev) && - np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, clear busy flag. */ - netif_wake_queue (dev); - } - /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & (IntrPCIErr | LinkChange | StatsMax)) - netdev_error(dev, intr_status); - } while (0); - if (netif_msg_intr(np)) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, ioread16(ioaddr + IntrStatus)); - return IRQ_RETVAL(handled); -} - -static void rx_poll(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = netdev_priv(dev); - int entry = np->cur_rx % RX_RING_SIZE; - int boguscnt = np->budget; - void __iomem *ioaddr = np->base; - int received = 0; - - /* If EOP is set on the next entry, it's a new packet. Send it up. */ - while (1) { - struct netdev_desc *desc = &(np->rx_ring[entry]); - u32 frame_status = le32_to_cpu(desc->status); - int pkt_len; - - if (--boguscnt < 0) { - goto not_done; - } - if (!(frame_status & DescOwn)) - break; - pkt_len = frame_status & 0x1fff; /* Chip omits the CRC. */ - if (netif_msg_rx_status(np)) - printk(KERN_DEBUG " netdev_rx() status was %8.8x.\n", - frame_status); - if (frame_status & 0x001f4000) { - /* There was a error. */ - if (netif_msg_rx_err(np)) - printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", - frame_status); - dev->stats.rx_errors++; - if (frame_status & 0x00100000) - dev->stats.rx_length_errors++; - if (frame_status & 0x00010000) - dev->stats.rx_fifo_errors++; - if (frame_status & 0x00060000) - dev->stats.rx_frame_errors++; - if (frame_status & 0x00080000) - dev->stats.rx_crc_errors++; - if (frame_status & 0x00100000) { - printk(KERN_WARNING "%s: Oversized Ethernet frame," - " status %8.8x.\n", - dev->name, frame_status); - } - } else { - struct sk_buff *skb; -#ifndef final_version - if (netif_msg_rx_status(np)) - printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" - ", bogus_cnt %d.\n", - pkt_len, boguscnt); -#endif - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ - if (pkt_len < rx_copybreak && - (skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) { - skb_reserve(skb, 2); /* 16 byte align the IP header */ - dma_sync_single_for_cpu(&np->pci_dev->dev, - le32_to_cpu(desc->frag[0].addr), - np->rx_buf_sz, DMA_FROM_DEVICE); - skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len); - dma_sync_single_for_device(&np->pci_dev->dev, - le32_to_cpu(desc->frag[0].addr), - np->rx_buf_sz, DMA_FROM_DEVICE); - skb_put(skb, pkt_len); - } else { - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(desc->frag[0].addr), - np->rx_buf_sz, DMA_FROM_DEVICE); - skb_put(skb = np->rx_skbuff[entry], pkt_len); - np->rx_skbuff[entry] = NULL; - } - skb->protocol = eth_type_trans(skb, dev); - /* Note: checksum -> skb->ip_summed = CHECKSUM_UNNECESSARY; */ - netif_rx(skb); - } - entry = (entry + 1) % RX_RING_SIZE; - received++; - } - np->cur_rx = entry; - refill_rx (dev); - np->budget -= received; - iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); - return; - -not_done: - np->cur_rx = entry; - refill_rx (dev); - if (!received) - received = 1; - np->budget -= received; - if (np->budget <= 0) - np->budget = RX_BUDGET; - tasklet_schedule(&np->rx_tasklet); -} - -static void refill_rx (struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - int entry; - int cnt = 0; - - /* Refill the Rx ring buffers. */ - for (;(np->cur_rx - np->dirty_rx + RX_RING_SIZE) % RX_RING_SIZE > 0; - np->dirty_rx = (np->dirty_rx + 1) % RX_RING_SIZE) { - struct sk_buff *skb; - entry = np->dirty_rx % RX_RING_SIZE; - if (np->rx_skbuff[entry] == NULL) { - skb = netdev_alloc_skb(dev, np->rx_buf_sz + 2); - np->rx_skbuff[entry] = skb; - if (skb == NULL) - break; /* Better luck next round. */ - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - np->rx_ring[entry].frag[0].addr = cpu_to_le32( - dma_map_single(&np->pci_dev->dev, skb->data, - np->rx_buf_sz, DMA_FROM_DEVICE)); - if (dma_mapping_error(&np->pci_dev->dev, - np->rx_ring[entry].frag[0].addr)) { - dev_kfree_skb_irq(skb); - np->rx_skbuff[entry] = NULL; - break; - } - } - /* Perhaps we need not reset this field. */ - np->rx_ring[entry].frag[0].length = - cpu_to_le32(np->rx_buf_sz | LastFrag); - np->rx_ring[entry].status = 0; - cnt++; - } -} -static void netdev_error(struct net_device *dev, int intr_status) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - u16 mii_ctl, mii_advertise, mii_lpa; - int speed; - - if (intr_status & LinkChange) { - if (mdio_wait_link(dev, 10) == 0) { - printk(KERN_INFO "%s: Link up\n", dev->name); - if (np->an_enable) { - mii_advertise = mdio_read(dev, np->phys[0], - MII_ADVERTISE); - mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); - mii_advertise &= mii_lpa; - printk(KERN_INFO "%s: Link changed: ", - dev->name); - if (mii_advertise & ADVERTISE_100FULL) { - np->speed = 100; - printk("100Mbps, full duplex\n"); - } else if (mii_advertise & ADVERTISE_100HALF) { - np->speed = 100; - printk("100Mbps, half duplex\n"); - } else if (mii_advertise & ADVERTISE_10FULL) { - np->speed = 10; - printk("10Mbps, full duplex\n"); - } else if (mii_advertise & ADVERTISE_10HALF) { - np->speed = 10; - printk("10Mbps, half duplex\n"); - } else - printk("\n"); - - } else { - mii_ctl = mdio_read(dev, np->phys[0], MII_BMCR); - speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; - np->speed = speed; - printk(KERN_INFO "%s: Link changed: %dMbps ,", - dev->name, speed); - printk("%s duplex.\n", - (mii_ctl & BMCR_FULLDPLX) ? - "full" : "half"); - } - check_duplex(dev); - if (np->flowctrl && np->mii_if.full_duplex) { - iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200, - ioaddr + MulticastFilter1+2); - iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl, - ioaddr + MACCtrl0); - } - netif_carrier_on(dev); - } else { - printk(KERN_INFO "%s: Link down\n", dev->name); - netif_carrier_off(dev); - } - } - if (intr_status & StatsMax) { - get_stats(dev); - } - if (intr_status & IntrPCIErr) { - printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", - dev->name, intr_status); - /* We must do a global reset of DMA to continue. */ - } -} - -static struct net_device_stats *get_stats(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - unsigned long flags; - u8 late_coll, single_coll, mult_coll; - - spin_lock_irqsave(&np->statlock, flags); - /* The chip only need report frame silently dropped. */ - dev->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); - dev->stats.tx_packets += ioread16(ioaddr + TxFramesOK); - dev->stats.rx_packets += ioread16(ioaddr + RxFramesOK); - dev->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); - - mult_coll = ioread8(ioaddr + StatsMultiColl); - np->xstats.tx_multiple_collisions += mult_coll; - single_coll = ioread8(ioaddr + StatsOneColl); - np->xstats.tx_single_collisions += single_coll; - late_coll = ioread8(ioaddr + StatsLateColl); - np->xstats.tx_late_collisions += late_coll; - dev->stats.collisions += mult_coll - + single_coll - + late_coll; - - np->xstats.tx_deferred += ioread8(ioaddr + StatsTxDefer); - np->xstats.tx_deferred_excessive += ioread8(ioaddr + StatsTxXSDefer); - np->xstats.tx_aborted += ioread8(ioaddr + StatsTxAbort); - np->xstats.tx_bcasts += ioread8(ioaddr + StatsBcastTx); - np->xstats.rx_bcasts += ioread8(ioaddr + StatsBcastRx); - np->xstats.tx_mcasts += ioread8(ioaddr + StatsMcastTx); - np->xstats.rx_mcasts += ioread8(ioaddr + StatsMcastRx); - - dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); - dev->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; - dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); - dev->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16; - - spin_unlock_irqrestore(&np->statlock, flags); - - return &dev->stats; -} - -static void set_rx_mode(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - u16 mc_filter[4]; /* Multicast hash filter */ - u32 rx_mode; - int i; - - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ - memset(mc_filter, 0xff, sizeof(mc_filter)); - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptAll | AcceptMyPhys; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to match, or accept all multicasts. */ - memset(mc_filter, 0xff, sizeof(mc_filter)); - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - } else if (!netdev_mc_empty(dev)) { - struct netdev_hw_addr *ha; - int bit; - int index; - int crc; - memset (mc_filter, 0, sizeof (mc_filter)); - netdev_for_each_mc_addr(ha, dev) { - crc = ether_crc_le(ETH_ALEN, ha->addr); - for (index=0, bit=0; bit < 6; bit++, crc <<= 1) - if (crc & 0x80000000) index |= 1 << bit; - mc_filter[index/16] |= (1 << (index % 16)); - } - rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys; - } else { - iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode); - return; - } - if (np->mii_if.full_duplex && np->flowctrl) - mc_filter[3] |= 0x0200; - - for (i = 0; i < 4; i++) - iowrite16(mc_filter[i], ioaddr + MulticastFilter0 + i*2); - iowrite8(rx_mode, ioaddr + RxMode); -} - -static int __set_mac_addr(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - u16 addr16; - - addr16 = (dev->dev_addr[0] | (dev->dev_addr[1] << 8)); - iowrite16(addr16, np->base + StationAddr); - addr16 = (dev->dev_addr[2] | (dev->dev_addr[3] << 8)); - iowrite16(addr16, np->base + StationAddr+2); - addr16 = (dev->dev_addr[4] | (dev->dev_addr[5] << 8)); - iowrite16(addr16, np->base + StationAddr+4); - return 0; -} - -/* Invoked with rtnl_lock held */ -static int sundance_set_mac_addr(struct net_device *dev, void *data) -{ - const struct sockaddr *addr = data; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - __set_mac_addr(dev); - - return 0; -} - -static const struct { - const char name[ETH_GSTRING_LEN]; -} sundance_stats[] = { - { "tx_multiple_collisions" }, - { "tx_single_collisions" }, - { "tx_late_collisions" }, - { "tx_deferred" }, - { "tx_deferred_excessive" }, - { "tx_aborted" }, - { "tx_bcasts" }, - { "rx_bcasts" }, - { "tx_mcasts" }, - { "rx_mcasts" }, -}; - -static int check_if_running(struct net_device *dev) -{ - if (!netif_running(dev)) - return -EINVAL; - return 0; -} - -static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct netdev_private *np = netdev_priv(dev); - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info)); -} - -static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - struct netdev_private *np = netdev_priv(dev); - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, ecmd); - spin_unlock_irq(&np->lock); - return 0; -} - -static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - struct netdev_private *np = netdev_priv(dev); - int res; - spin_lock_irq(&np->lock); - res = mii_ethtool_sset(&np->mii_if, ecmd); - spin_unlock_irq(&np->lock); - return res; -} - -static int nway_reset(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - return mii_nway_restart(&np->mii_if); -} - -static u32 get_link(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - return mii_link_ok(&np->mii_if); -} - -static u32 get_msglevel(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - return np->msg_enable; -} - -static void set_msglevel(struct net_device *dev, u32 val) -{ - struct netdev_private *np = netdev_priv(dev); - np->msg_enable = val; -} - -static void get_strings(struct net_device *dev, u32 stringset, - u8 *data) -{ - if (stringset == ETH_SS_STATS) - memcpy(data, sundance_stats, sizeof(sundance_stats)); -} - -static int get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(sundance_stats); - default: - return -EOPNOTSUPP; - } -} - -static void get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct netdev_private *np = netdev_priv(dev); - int i = 0; - - get_stats(dev); - data[i++] = np->xstats.tx_multiple_collisions; - data[i++] = np->xstats.tx_single_collisions; - data[i++] = np->xstats.tx_late_collisions; - data[i++] = np->xstats.tx_deferred; - data[i++] = np->xstats.tx_deferred_excessive; - data[i++] = np->xstats.tx_aborted; - data[i++] = np->xstats.tx_bcasts; - data[i++] = np->xstats.rx_bcasts; - data[i++] = np->xstats.tx_mcasts; - data[i++] = np->xstats.rx_mcasts; -} - -static const struct ethtool_ops ethtool_ops = { - .begin = check_if_running, - .get_drvinfo = get_drvinfo, - .get_settings = get_settings, - .set_settings = set_settings, - .nway_reset = nway_reset, - .get_link = get_link, - .get_msglevel = get_msglevel, - .set_msglevel = set_msglevel, - .get_strings = get_strings, - .get_sset_count = get_sset_count, - .get_ethtool_stats = get_ethtool_stats, -}; - -static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct netdev_private *np = netdev_priv(dev); - int rc; - - if (!netif_running(dev)) - return -EINVAL; - - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - - return rc; -} - -static int netdev_close(struct net_device *dev) -{ - struct netdev_private *np = netdev_priv(dev); - void __iomem *ioaddr = np->base; - struct sk_buff *skb; - int i; - - /* Wait and kill tasklet */ - tasklet_kill(&np->rx_tasklet); - tasklet_kill(&np->tx_tasklet); - np->cur_tx = 0; - np->dirty_tx = 0; - np->cur_task = 0; - np->last_tx = NULL; - - netif_stop_queue(dev); - - if (netif_msg_ifdown(np)) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %2.2x " - "Rx %4.4x Int %2.2x.\n", - dev->name, ioread8(ioaddr + TxStatus), - ioread32(ioaddr + RxStatus), ioread16(ioaddr + IntrStatus)); - printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", - dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); - } - - /* Disable interrupts by clearing the interrupt mask. */ - iowrite16(0x0000, ioaddr + IntrEnable); - - /* Disable Rx and Tx DMA for safely release resource */ - iowrite32(0x500, ioaddr + DMACtrl); - - /* Stop the chip's Tx and Rx processes. */ - iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); - - for (i = 2000; i > 0; i--) { - if ((ioread32(ioaddr + DMACtrl) & 0xc000) == 0) - break; - mdelay(1); - } - - iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset, - ioaddr + ASIC_HI_WORD(ASICCtrl)); - - for (i = 2000; i > 0; i--) { - if ((ioread16(ioaddr + ASIC_HI_WORD(ASICCtrl)) & ResetBusy) == 0) - break; - mdelay(1); - } - -#ifdef __i386__ - if (netif_msg_hw(np)) { - printk(KERN_DEBUG " Tx ring at %8.8x:\n", - (int)(np->tx_ring_dma)); - for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n", - i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr, - np->tx_ring[i].frag[0].length); - printk(KERN_DEBUG " Rx ring %8.8x:\n", - (int)(np->rx_ring_dma)); - for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) { - printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", - i, np->rx_ring[i].status, np->rx_ring[i].frag[0].addr, - np->rx_ring[i].frag[0].length); - } - } -#endif /* __i386__ debugging only */ - - free_irq(dev->irq, dev); - - del_timer_sync(&np->timer); - - /* Free all the skbuffs in the Rx queue. */ - for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].status = 0; - skb = np->rx_skbuff[i]; - if (skb) { - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(np->rx_ring[i].frag[0].addr), - np->rx_buf_sz, DMA_FROM_DEVICE); - dev_kfree_skb(skb); - np->rx_skbuff[i] = NULL; - } - np->rx_ring[i].frag[0].addr = cpu_to_le32(0xBADF00D0); /* poison */ - } - for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_ring[i].next_desc = 0; - skb = np->tx_skbuff[i]; - if (skb) { - dma_unmap_single(&np->pci_dev->dev, - le32_to_cpu(np->tx_ring[i].frag[0].addr), - skb->len, DMA_TO_DEVICE); - dev_kfree_skb(skb); - np->tx_skbuff[i] = NULL; - } - } - - return 0; -} - -static void __devexit sundance_remove1 (struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - struct netdev_private *np = netdev_priv(dev); - unregister_netdev(dev); - dma_free_coherent(&pdev->dev, RX_TOTAL_SIZE, - np->rx_ring, np->rx_ring_dma); - dma_free_coherent(&pdev->dev, TX_TOTAL_SIZE, - np->tx_ring, np->tx_ring_dma); - pci_iounmap(pdev, np->base); - pci_release_regions(pdev); - free_netdev(dev); - pci_set_drvdata(pdev, NULL); - } -} - -#ifdef CONFIG_PM - -static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pci_dev); - - if (!netif_running(dev)) - return 0; - - netdev_close(dev); - netif_device_detach(dev); - - pci_save_state(pci_dev); - pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); - - return 0; -} - -static int sundance_resume(struct pci_dev *pci_dev) -{ - struct net_device *dev = pci_get_drvdata(pci_dev); - int err = 0; - - if (!netif_running(dev)) - return 0; - - pci_set_power_state(pci_dev, PCI_D0); - pci_restore_state(pci_dev); - - err = netdev_open(dev); - if (err) { - printk(KERN_ERR "%s: Can't resume interface!\n", - dev->name); - goto out; - } - - netif_device_attach(dev); - -out: - return err; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver sundance_driver = { - .name = DRV_NAME, - .id_table = sundance_pci_tbl, - .probe = sundance_probe1, - .remove = __devexit_p(sundance_remove1), -#ifdef CONFIG_PM - .suspend = sundance_suspend, - .resume = sundance_resume, -#endif /* CONFIG_PM */ -}; - -static int __init sundance_init(void) -{ -/* when a module, this is printed whether or not devices are found in probe */ -#ifdef MODULE - printk(version); -#endif - return pci_register_driver(&sundance_driver); -} - -static void __exit sundance_exit(void) -{ - pci_unregister_driver(&sundance_driver); -} - -module_init(sundance_init); -module_exit(sundance_exit); - - |