Patch/Announce: linux-2.4.0-test5/drivers/net/dp83815.c (Nat. Semi. 10/100 ethernet driver)

From: Adam J. Richter (adam@yggdrasil.com)
Date: Sat Jul 29 2000 - 03:23:17 EST


        As promised, here is my port for 2.4.0-test5 of the National
Semiconductor DP83815 10/100Mbps ethernet driver that, as I understand,
was originally written for the 2.0.x kernels by somebody at National
Semicondutor, given to Wyse Technologies, where it was cleaned up,
ported to 2.2.x, and then turned over by Dave Gottwisner of Wyse to me
for the purpose of shepherding it into the stock kernels. I posted
the Wyse driver for 2.0.x/2.2.x kernel verbatim a day or two ago. Now,
I am posting my port of the driver to 2.4.0-test5. I would appreciate
it if people would look at it, try it, and send feedback or patches to
me. I am writing this email from a machine using a DP83815 card as its
network device, running 2.4.0-test5, so it at least works for me.

        The DP83815 is used in some very inexpensive networking cards,
and can support Wake-on-LAN. The last time I looked at ethernet cards
in a local computer store, there were DP83815 based cards available for
~$15, while all other cards that supported Wake-on-LAN started at ~$50.
So, this driver may save a lot of users a little bit of money.

Adam J. Richter __ ______________ 4880 Stevens Creek Blvd, Suite 104
adam@yggdrasil.com \ / San Jose, California 95129-1034
+1 408 261-6630 | g g d r a s i l United States of America
fax +1 408 261-6631 "Free Software For The Rest Of Us."
---------------------------CUT HERE--------------------------------------

--- linux-2.4.0-test5/drivers/net/dp83815.c Sat Jul 29 01:09:55 2000
+++ linux/drivers/net/dp83815.c Sat Jul 29 00:47:48 2000
@@ -0,0 +1,1426 @@
+/* DP83815.c -- National Semiconductor DP83815 PCI Ethernet Controller Driver */
+
+static const char product_version[] = "dp83815.c:v1.30 National Semiconductor DP83815 PCI Ethernet Driver\n";
+
+/*
+1. INTRODUCTION
+---------------
+
+The DP83815 is a PCI bus based single chip 10/100 Mbps ethernet
+controller targeted for PC mother boards, adapter cards, and embedded
+systems. It fully implements the V2.2 33MHz PCI bus interface for host
+communications with power management support. Packet descriptors and
+data are transferred via bus-mastering, reducing the burden on the
+host CPU. The DP83815 can support full duplex 10/100 Mbps transmission
+and reception. This driver has been updated to support rev C of the chip.
+
+The DP83815 driver is developed for use on Linux v2.0.X and v2.2.X and
+has been tested with 2.0.36 and 2.2.13 versions of the kernel.It can be
+configured either as a static driver into the kernel or as a loadable
+module. The driver is capable of 10/100 Mbps Full/Half duplex mode
+operation via an internal PHY. Detailed features are given below.
+
+2.1 Chip Features
+
+ o The chip is bus-master capable and transfers packet descriptors
+ and data using DMA with burst sizes upto 128 words.
+
+ o It supports 10 Mbps Ethernet and 100 Mbps Fast Ethernet via
+ an internal PHY and emerging 1-2 Mbps home networking
+ solutions via external PHY.
+
+ o Flexible Rx packet filtration including: perfect match, broadcast,
+ multicast/unicast hash table, deep packet pattern matching.
+
+ o Internal Tx and Rx data FIFOs of 2KB each
+
+ o 802.3u Auto-Negotiation - advertised features configurable via
+ EEPROM
+
+ o Full duplex support for 10 and 100Mb/s data rates
+
+
+2.2 Driver Features
+
+2.2.1 Supported Features
+
+ o 10 Mbps full duplex and half duplex
+ o 100 Mbps full duplex and half duplex
+ o Auto Negotiation
+ o Broadcast and perfect match transmit and receive
+ o ARP transmit and receive
+ o Promiscuous mode
+ o Multicast support
+ o Loadable Kernel Module
+ o PCI bus probe for auto-configuration when configured as a static
+ driver or a loadable kernel module
+ o Endian, and CPU architecture neutral
+ o Supports rev C of the chip
+ o 2.0.xx and 2.2.xx Linux kernels
+
+2.2.2 Unsupported Features
+
+ o ACPI
+ o Multiple ethernet addresses
+ o Wake on LAN and OnNow support for PC98/99, and other power-management
+ features.
+ o Magic packets with SecureON, VLAN
+ o Programming EEPROM/Flash
+ o Old Linux kernels 1.xx.xx
+ o Newer MP kernels 2.2.xx
+ o Remote boot
+
+
+3. DRIVER OPERATION
+-------------------
+
+Buffer management used in this version of the driver sets up the
+transmit and receive buffer descriptors in a ring. The rings, shared
+between the driver and the device, are located in memory buffers
+allocated in the kernel. The device accesses these buffers via DMA.
+
+Each device will be allocated two similar queues of descriptors, one
+for transmit and the other for receive. These queues are linked
+together into a ring. For the default size of the transmit rings is
+10, while the size of the receive ring is 30. These values can be
+changed via macros in the driver source file.
+
+The driver implements no copy transmits. All transmit descriptors are
+created with no associated buffers, but the descriptor uses the
+sk_buff passed to it via the transmit routine. The sk_buff is held by
+the driver until the next transmit operation that follows the actual
+transmit of the packet.
+
+Each receive descriptor is initialized, at creation time, with an
+sk_buff. Each sk_buff has a data buffer that can hold a max ethernet
+packet. When a packet is suceesfully received, the skb is directly
+sent to the stack with no copy, and it is replaced with a newly
+allocated sk_buff. But if the packet less than 128 bytes
+was received, the data is instead copied into a new skb.
+
+The driver makes of appropriate macros to adjust for endian-ness of
+the host CPU, PCI bus, Ethernet, and the DP device. It also performs
+appropriate translations of addresses for device use. These builtin
+features makes the driver extremely portable to run on Linux systems
+with non-Intel CPUs with minimum changes.
+
+The driver has a table, dp83815_ids[] to store the hardware_id
+information for the DP83815 device from all Vendors. In this version
+of the driver, the dp83815_ids has only one entry for the
+vendor_id and board_id of the NS_DP83815. If the device's ID differs
+from these values, the table should be extended with the new values.
+
+
+4. FUNCTIONALITY TESTING
+------------------------
+
+When the driver is loaded into the system via `insmod' it probes the
+PCI bus to locate all DP83815 devices, and creates control structures
+for each. The driver logs a couple of messages available in
+`/var/log/messages' for each device with information about its PCI
+geographic location, IRQ, IO address, and some basic debug information
+(addresses of some important structures).
+
+All the devices on the PCI bus can be listed by,
+
+ # cat /proc/pci
+
+IRQ and IO address information from this can be correlated with the
+information displayed by the driver in `/var/log/messages'
+
+When the TCP/IP stack is initialized, it opens all configured ethernet
+devices, and initializes them for use. At this time, the driver will
+perform autonegotiation and log information about the link status.
+The driver can then be tested by running ping, telnet, ftp, NFS etc.
+
+
+5. KNOWN DRIVER PROBLEMS
+------------------------
+
+o Since the device requires that the receive buffer be aligned on a
+ 4-byte (word) boundary, it is not possible to align the IP header
+ on a word boundary unless the received packet is copied. Since this
+ version of the driver support a no-copy receive operation, the IP
+ header will not be aligned. This is not a problem for Intel CPUs,
+ but will cause exceptions on RISC CPUs (PowerPC, Alpha, ...). While
+ porting the driver to these platforms, the no-copy receive can be
+ turned off, but setting the DP_RX_COPY_THRESHOLD to ETH_MAX_PKT_SIZE,
+ whereby forcing all receive buffers to be copied.
+
+ The driver ensures that the IP headers in a copied buffer is aligned
+ on a word-boundary.
+
+6. REVISION HISTORY
+--------------------
+
+v1.30 : support for Linux Kernel 2.2 was added
+
+v1.20 : proper initialisation of TXCFG and RXCFG registers for full duplex
+ mode was done.
+ in start_xmit, BUFPTR was updated prior to CMDSTS of the descriptor
+ infinite loop in case of dev_reset failure was corrected.
+
+v1.10 : this is the first release of the driver
+
+7. DOCUMENTATION REFERENCES
+---------------------------
+
+1. National Semiconductor DP83815 10/100 Mb/s Integrated PCI Ethernet
+ Media Access Controller and Physical Layer, 1998.
+2. Linux Device Drivers, Alessandro Rubini, 1998.
+
+
+ Authorship and other copyrights (the drivers from which this
+ software was derived):
+ 1992-1998 by Donald Becker, NE2000 core and various modifications.
+ 1995-1998 by Paul Gortmaker, core modifications and PCI support.
+
+ Port to the DP83815:
+ Copyright 1999 National Semiconductor Corporation
+ Copyright 2000 Wyse Technologies, Inc.
+ Copyright 2000 Yggdrasil Computing, Inc.
+
+ Copyright 1993 assigned to the United States Government as represented
+ by the Director, National Security Agency.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+*/
+
+/* Generic Kernel Module/Driver Headers */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/io.h> /* IO stuff */
+#include <asm/byteorder.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+/* Ethernet Driver Specific Headers */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/malloc.h>
+#include <linux/if_ether.h>
+
+#include "dp83815.h"
+
+/*
+ * SWAP_BUS_TO_CPU_XX and SWAP_CPU_TO_BUS_XX macros swap 16 and 32 bit values
+ * between the PCI bus' little endian byte-order and the CPU's native
+ * byte-order.
+ */
+#ifdef __BIG_ENDIAN
+#define BUS_TO_CPU_SWAP_16(X) swap_16(X)
+#define BUS_TO_CPU_SWAP_32(X) swap_32(X)
+#define CPU_TO_BUS_SWAP_16(X) swap_16(X)
+#define CPU_TO_BUS_SWAP_32(X) swap_32(X)
+#define CPU_TO_NET_SWAP_16(X) ((u16)(X))
+#define CPU_TO_NET_SWAP_32(X) ((u32)(X))
+#define NET_TO_CPU_SWAP_16(X) ((u16)(X))
+#define NET_TO_CPU_SWAP_32(X) ((u32)(X))
+#else
+#define BUS_TO_CPU_SWAP_32(X) ((u32)(X))
+#define BUS_TO_CPU_SWAP_16(X) ((u16)(X))
+#define CPU_TO_BUS_SWAP_32(X) ((u32)(X))
+#define CPU_TO_BUS_SWAP_16(X) ((u16)(X))
+#define CPU_TO_NET_SWAP_16(X) swap_16(X)
+#define CPU_TO_NET_SWAP_32(X) swap_32(X)
+#define NET_TO_CPU_SWAP_16(X) swap_16(X)
+#define NET_TO_CPU_SWAP_32(X) swap_32(X)
+#endif
+
+/* Macros translate addresses between PCI bus and CPU */
+#define BUS_TO_CPU_ADDR_XLATE(X) BUS_TO_CPU_SWAP_32(bus_to_virt(X))
+#define CPU_TO_BUS_ADDR_XLATE(X) CPU_TO_BUS_SWAP_32(virt_to_bus(X))
+
+/* Macros to read/write 32/16 bit data to/from DP83815 device registers. */
+#define DP_REG32_WRITE(reg, val) io_write_32 (iobase+(reg), \
+ CPU_TO_BUS_SWAP_32(val))
+#define DP_REG32_READ(reg) BUS_TO_CPU_SWAP_32(io_read_32 (iobase+(reg)))
+#define DP_REG16_WRITE(reg, val) io_write_16 (iobase+(reg), \
+ CPU_TO_BUS_SWAP_16(val))
+#define DP_REG16_READ(reg) BUS_TO_CPU_SWAP_16(io_read_16 (iobase+(reg)))
+#define DP_REG32_SET(reg, val) DP_REG32_WRITE(reg,DP_REG32_READ(reg)|(val))
+#define DP_REG32_CLR(reg, val) DP_REG32_WRITE(reg,DP_REG32_READ(reg)&~(val))
+#define DP_REG16_SET(reg, val) DP_REG16_WRITE(reg,DP_REG16_READ(reg)|(val))
+#define DP_REG16_CLR(reg, val) DP_REG16_WRITE(reg,DP_REG16_READ(reg)&~(val))
+
+/* Debug Macros */
+#define DP_DEBUG_PROBE 0x00000001
+#define DP_DEBUG_OPEN 0x00000002
+#define DP_DEBUG_CLOSE 0x00000004
+#define DP_DEBUG_IOCTL 0x00000008
+#define DP_DEBUG_TX 0x00000010
+#define DP_DEBUG_RX 0x00000020
+#define DP_DEBUG_MC 0x00000040
+#define DP_DEBUG_ANEG 0x00000080
+#define DP_DEBUG_INTR 0x00000100
+#define DP_DEBUG_LOAD 0x00000200
+#define DP_DEBUG_UNLOAD 0x00000400
+
+#if (DRV_DEBUG > 0)
+u32 dp_debug_level=DRV_DEBUG;
+#define DP_DEBUG(level, X) if (level & dp_debug_level) printk X
+#else
+#define DP_DEBUG(level, X)
+#endif
+
+/* data types */
+typedef u32 status; /* return status */
+typedef volatile u8 * virt_addr; /* CPU virtual address */
+typedef volatile u8 * bus_addr; /* BUS physical address */
+typedef u8 bool;
+
+#define OK 0 /* status: OK */
+#define ERROR -1 /* status: ERROR */
+#define TRUE 1
+#define FALSE 0
+
+bool dp_full_duplex; /* flag for full duplex mode */
+
+/* Default Driver Parameters */
+#define DP_DEFAULT_TXQ_SIZE 10
+#define DP_DEFAULT_RXQ_SIZE 30
+#define DP_RX_COPY_THRESHOLD 128 /* upper limit for rx packet copy */
+#define DP_POLYNOMIAL 0x04C11DB6
+
+/* Alignment and packet sizes */
+#define ETH_CRC_LEN 4
+#define ETH_MAX_PKT_SIZE (ETH_FRAME_LEN + ETH_CRC_LEN)
+#define DP_ALIGN 4 /* word alignment */
+
+/* Driver private descriptor macros */
+#define DP_DESC_SKBPTR 0x0c /* SKB pointer offset */
+#define DP_QUEUE_ELE_SIZE (DP_DESC_SIZE + 4)
+#define DP_QUEUE_ELE_NEXT(q) \
+ q->cur_desc_addr = DP_QUEUE_ELE_NEXT_GET(q, q->cur_desc_addr)
+#define DP_QUEUE_ELE_NEXT_GET(q, desc_addr) \
+ ((desc_addr) == (q)->last_desc_addr) ? (q)->first_desc_addr : \
+ (desc_addr) + DP_QUEUE_ELE_SIZE
+
+/* Macros to get/set the values of the descriptor fields */
+#define DP_DESC_LNK_GET(ptr) *(u32 *)((virt_addr)ptr + DP_DESC_LNK)
+#define DP_DESC_CMDSTS_GET(ptr) *(u32 *)((virt_addr)ptr + DP_DESC_CMDSTS)
+#define DP_DESC_BUFPTR_GET(ptr) *(u32 *)((virt_addr)ptr + DP_DESC_BUFPTR)
+#define DP_DESC_SKBPTR_GET(ptr) *(u32 *)((virt_addr)ptr + DP_DESC_SKBPTR)
+
+#define DP_DESC_LNK_SET(ptr, val) DP_DESC_LNK_GET(ptr) = (val)
+#define DP_DESC_CMDSTS_SET(ptr, val) DP_DESC_CMDSTS_GET(ptr) = (val)
+#define DP_DESC_BUFPTR_SET(ptr,val) DP_DESC_BUFPTR_GET(ptr) = (val)
+#define DP_DESC_SKBPTR_SET(ptr,val) DP_DESC_SKBPTR_GET(ptr) = (val)
+
+/*
+ * Macros to get/set the values of descriptor fields with
+ * appropriate address and byte order translations
+ */
+#define DP_DESC_LNK_XLATE_GET(p) BUS_TO_CPU_ADDR_XLATE(DP_DESC_LNK_GET(p))
+#define DP_DESC_CMDSTS_XLATE_GET(p) BUS_TO_CPU_SWAP_32(DP_DESC_CMDSTS_GET(p))
+#define DP_DESC_BUFPTR_XLATE_GET(p) BUS_TO_CPU_ADDR_XLATE(DP_DESC_BUFPTR_GET(p))
+
+#define DP_DESC_LNK_XLATE_SET(p, v) \
+ DP_DESC_LNK_SET(p, CPU_TO_BUS_ADDR_XLATE(v))
+#define DP_DESC_CMDSTS_XLATE_SET(p, v) \
+ DP_DESC_CMDSTS_SET(p, CPU_TO_BUS_SWAP_32(v))
+#define DP_DESC_BUFPTR_XLATE_SET(p,v) \
+ DP_DESC_BUFPTR_SET(p, CPU_TO_BUS_ADDR_XLATE(v))
+
+#ifndef PCI_VENDOR_ID_NS
+#define PCI_VENDOR_ID_NS 0x100b
+#endif
+
+/* Descriptor queue */
+struct dp83815_queue
+{
+ virt_addr first_desc_addr; /* descriptor array address */
+ virt_addr last_desc_addr; /* last descriptor address */
+ virt_addr cur_desc_addr; /* current descriptor address */
+ virt_addr qbuf; /* allocated queue buffer */
+ u16 count; /* number of elements */
+};
+
+/* Queue types -- qtype */
+#define DP_QUEUE_TYPE_TX 1 /* Transmit queue */
+#define DP_QUEUE_TYPE_RX 2 /* Receive queue */
+
+/* Device private data */
+struct dp83815_priv
+{
+ struct dp83815_queue tx_queue; /* Transmit Descriptor Queue */
+ struct dp83815_queue rx_queue; /* Receive Descriptor Queue */
+ struct net_device_stats stats; /* MIB data */
+ char hw_mac_addr [ETH_ALEN]; /* Factory Ethernet Address */
+};
+
+/* Table for hardware_id information of the DP device. The first entry
+ to the table is the vendor_id and board_id for NS's Dp83815. Other
+ Vendors' extensions to the DP device should be added to this table.
+*/
+
+static struct pci_device_id dp83815_ids[] =
+{
+ { PCI_VENDOR_ID_NS, PCI_PRODUCT_ID_NS_83815, PCI_ANY_ID, PCI_ANY_ID,0,0,0}
+};
+MODULE_DEVICE_TABLE(pci, dp83815_ids);
+
+/* Linux Network Driver interface routines */
+extern int dp83815_probe (struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static int dp83815_open (struct net_device *dev);
+static int dp83815_close (struct net_device *dev);
+static int dp83815_start_xmit (struct sk_buff *skb, struct net_device *dev);
+static void dp83815_set_multicast_list (struct net_device *dev);
+static int dp83815_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static void dp83815_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats *dp83815_get_stats (struct net_device *dev);
+
+/* Support Functions */
+static u16 swap_16 (u16 us);
+/*static u32 swap_32 (u32 ui);*/
+static u32 io_read_32 (u16 io_port);
+static void io_write_32 (u16 io_port, u32 data);
+static u16 io_read_16 (u16 io_port);
+/*static void io_write_16 (u16 io_port, u16 data);*/
+
+/* Driver Private Routines */
+static void dp83815_mac_address_set (u32 iobase, char *mac_addr);
+static void dp83815_mac_address_get (u32 iobase, char *mac_addr);
+static status dp83815_dev_reset (u32 iobase);
+static status dp83815_queue_create (struct dp83815_queue *q, int count, int qtype);
+static status dp83815_queue_delete (struct dp83815_queue *q);
+static virt_addr dp83815_tx_desc_get (struct net_device *dev);
+static virt_addr dp83815_rx_desc_get (struct net_device *dev);
+static status dp83815_phy_setup (struct net_device *dev);
+static int dp83815_crc (char * mc_addr);
+static void dp83815_tx_skb_reclaim (struct net_device *dev, virt_addr desc_addr);
+
+/* Driver Debug Routines */
+#if (DRV_DEBUG > 0)
+static void dp83815_regs_info (u16 iobase);
+#endif
+
+/*
+ * dp83815_probe - enumerate the PCI bus for instances of DP83815
+ *
+ * This routine enumerates DP83815 ethernet devices on the PCI bus, and
+ * registers each DP83815 device found.
+ */
+int
+dp83815_probe (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int i;
+ u8 irq;
+ unsigned long iobase;
+ u32 version;
+ char ether_addr[ETH_ALEN];
+ struct dp83815_priv * priv;
+ struct net_device *dev;
+
+ iobase = pci_resource_start(pdev, 0);
+ irq = pdev->irq;
+
+ if (!iobase || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
+ printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n");
+ return -ENODEV;
+ }
+
+ i = pci_enable_device (pdev);
+ if (i)
+ return i;
+
+ if (request_region (iobase, DP83815_PCI_IO_SIZE, "ne2k-pci") == NULL) {
+ printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n",
+ DP83815_PCI_IO_SIZE, iobase);
+ return -EBUSY;
+ }
+
+
+ dp83815_mac_address_get (iobase, ether_addr);
+
+ /* Put the device in a quiescent state */
+ if (dp83815_dev_reset (iobase) != OK) {
+ printk (KERN_INFO "%s: Device Reset failed -- iobase=0x%lx.\n",
+ DP_DRV_NAME, iobase);
+ goto err_out_free_res;
+ }
+
+ dev = init_etherdev(NULL, sizeof (struct dp83815_priv));
+
+ if (dev == NULL)
+ {
+ printk (KERN_INFO "%s: Failed to allocate device struct -- "
+ " iobase=0x%lx\n",
+ DP_DRV_NAME, iobase);
+ goto err_out_free_res;
+ }
+
+ memset(dev->priv, 0, sizeof(struct dp83815_priv));
+ priv=(struct dp83815_priv *)dev->priv;
+
+ /* Save ethernet address */
+ memcpy (dev->dev_addr, ether_addr, ETH_ALEN);
+ memcpy (priv->hw_mac_addr, ether_addr, ETH_ALEN);
+
+ /* If address is not set, set up a default one */
+ if ((dev->dev_addr[0] == 0) && (dev->dev_addr[1] == 0) &&
+ (dev->dev_addr[2] == 0) && (dev->dev_addr[3] == 0) &&
+ (dev->dev_addr[4] == 0) && (dev->dev_addr[5] == 0))
+ {
+ u32 random = jiffies;
+ u8 * ptr = (u8 *) &random;
+
+ dev->dev_addr[0] = 0x08; /* National's Ethernet ID 0 */
+ dev->dev_addr[1] = 0x00; /* National's Ethernet ID 1 */
+ dev->dev_addr[2] = 0x17; /* National's Ethernet ID 2 */
+ dev->dev_addr[3] = *ptr++;
+ dev->dev_addr[4] = *ptr++;
+ dev->dev_addr[5] = *ptr;
+ } else if ((dev->dev_addr[0] == 0x00) && (dev->dev_addr[1] == 0x08))
+ {
+ /* Buggy ethernet address; needs swapping */
+ u16 * ptr = (u16 *) dev->dev_addr;
+ u8 i;
+
+ for (i=0; i<3; i++)
+ {
+ *ptr = swap_16(*ptr);
+ ptr++;
+ }
+ }
+
+ dp83815_mac_address_set (iobase, dev->dev_addr);
+
+ /* initialize the device data */
+ pdev->driver_data = dev;
+ dev->base_addr = iobase;
+ dev->irq = irq;
+ dev->open = dp83815_open;
+ dev->stop = dp83815_close;
+ dev->get_stats = dp83815_get_stats;
+ dev->do_ioctl = dp83815_ioctl;
+ dev->hard_start_xmit = dp83815_start_xmit;
+ dev->set_multicast_list = dp83815_set_multicast_list;
+
+ /* reserve IO region */
+ request_region (iobase, DP83815_PCI_IO_SIZE, dev->name);
+
+ /* Display board info */
+ version = DP_REG32_READ(DP_SRR);
+ printk (KERN_INFO "%s: io=0x%lx irq=%d ver=%d.%d\n",
+ dev->name, iobase, irq,
+ (version & DP_SRR_MAJ) >> DP_SRR_MAJ_SHF,
+ (version & DP_SRR_MIN));
+
+ printk (KERN_INFO "%s: ethernet addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+#ifdef DEBUG
+ printk (KERN_INFO "%s: DebugInfo: dev=0x%x priv=0x%x "
+ "&dp_debug_level=0x%x\n",
+ dev->name, (u32)dev, (u32)dev->priv, (u32)&dp_debug_level);
+#endif
+
+ return OK;
+
+err_out_free_res:
+ release_region (iobase, DP83815_PCI_IO_SIZE);
+ return -ENODEV;
+}
+
+/* dp83815_open - open and initialize a device */
+static int
+dp83815_open (struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ struct dp83815_priv* priv = dev->priv;
+
+ /* Allocate Tx and Rx queues */
+ if (dp83815_queue_create (&priv->tx_queue, DP_DEFAULT_TXQ_SIZE, DP_QUEUE_TYPE_TX) != OK)
+ {
+ printk (KERN_INFO "%s: Failed to create tx queue\n", dev->name);
+ return -EAGAIN;
+ }
+
+ if (dp83815_queue_create (&priv->rx_queue, DP_DEFAULT_RXQ_SIZE, DP_QUEUE_TYPE_RX) != OK)
+ {
+ dp83815_queue_delete (&priv->tx_queue);
+ printk (KERN_INFO "%s: Failed to create rx queue\n", dev->name);
+ return -EAGAIN;
+ }
+
+ /* Install the Tx and Rx queues on the device */
+ DP_REG32_WRITE (DP_TXDP, virt_to_bus(priv->tx_queue.first_desc_addr));
+ DP_REG32_WRITE (DP_RXDP, virt_to_bus(priv->rx_queue.first_desc_addr));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp: setting TXDP=0x%x RXDP=0x%x\n",
+ (u32)virt_to_bus (priv->tx_queue.first_desc_addr),
+ (u32)virt_to_bus (priv->rx_queue.first_desc_addr)));
+
+ /* Install interrupt vector */
+ if (request_irq (dev->irq, &dp83815_interrupt, SA_SHIRQ, dev->name, dev) != OK)
+ {
+ dp83815_queue_delete (&priv->tx_queue);
+ dp83815_queue_delete (&priv->rx_queue);
+ return -EAGAIN;
+ }
+
+ /* Setup phy capabilities */
+ if (dp83815_phy_setup (dev) != OK)
+ {
+ printk (KERN_INFO "%s: Warning PHY setup did not complete. Check cable.\n",
+ dev->name);
+ }
+
+ /* setup transmit and receive control according to duplexity of Phy */
+
+ if (dp_full_duplex)
+ {
+ /* Setup transmit control */
+
+ DP_REG32_WRITE (DP_TXCFG, (DP_TXCFG_DRTH_SET(0x30) |
+ DP_TXCFG_FLTH_SET(0x10) |
+ DP_TXCFG_MXDMA_32 |
+ DP_TXCFG_ATP |
+ DP_TXCFG_CSI |
+ DP_TXCFG_HBI));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp (Full Duplex): TXCFG set to 0x%x\n",
+ (DP_TXCFG_DRTH_SET(0x30) | DP_TXCFG_FLTH_SET(0x10) |
+ DP_TXCFG_MXDMA_32 | DP_TXCFG_ATP |
+ DP_TXCFG_CSI | DP_TXCFG_HBI)));
+
+ /* Setup receive control */
+
+ DP_REG32_WRITE (DP_RXCFG, (DP_RXCFG_DRTH_SET(0x08) |
+ DP_RXCFG_MXDMA_32 |
+ DP_RXCFG_ATX));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp (Full Duplex): RXCFG set to 0x%x\n",
+ (DP_RXCFG_DRTH_SET(0x08) | DP_RXCFG_MXDMA_32 |
+ DP_RXCFG_ATX)));
+ } else
+ {
+ /* Setup transmit control */
+
+ DP_REG32_WRITE (DP_TXCFG, (DP_TXCFG_DRTH_SET(0x30) |
+ DP_TXCFG_FLTH_SET(0x10) |
+ DP_TXCFG_MXDMA_32 |
+ DP_TXCFG_ATP));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp (Half Duplex): TXCFG set to 0x%x\n",
+ (DP_TXCFG_DRTH_SET(0x30) | DP_TXCFG_FLTH_SET(0x10) |
+ DP_TXCFG_MXDMA_32 | DP_TXCFG_ATP)));
+
+ /* Setup receive control */
+
+ DP_REG32_WRITE (DP_RXCFG, (DP_RXCFG_DRTH_SET(0x08) |
+ DP_RXCFG_MXDMA_32));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp (Half Duplex): RXCFG set to 0x%x\n",
+ (DP_RXCFG_DRTH_SET(0x08) | DP_RXCFG_MXDMA_32)));
+ }
+
+ /* Setup the ethernet address */
+ dp83815_mac_address_set (iobase, dev->dev_addr);
+
+ /* Receive perfect match and broadcast packets */
+ DP_REG32_WRITE (DP_RFCR, 0);
+ DP_REG32_WRITE (DP_RFCR, (DP_RFCR_AAB | /* all broadcast pkts */
+ DP_RFCR_APM | /* perfect match pkts */
+ DP_RFCR_RFEN));
+
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "dp: RFCR set to 0x%x\n",
+ DP_RFCR_RFEN | DP_RFCR_APM | DP_RFCR_AAB));
+
+ /* Turn on device interrupts -- the driver only looks at RXOK, not any of
+ * the others, so we might as well not turn them on.
+ */
+ //DP_REG32_WRITE (DP_IMR, (DP_IMR_RXOK | DP_IMR_MIB |
+ //DP_IMR_RTABT | DP_IMR_RMABT |
+ //DP_IMR_SSERR | DP_IMR_PHY));
+ DP_REG32_WRITE (DP_IMR, (DP_IMR_RXOK));
+ DP_REG32_WRITE (DP_IER, DP_IER_IE);
+
+ /* Enable Tx/Rx */
+ DP_REG32_WRITE (DP_CR, DP_CR_TXE | DP_CR_RXE);
+
+ /* Increment module reference count */
+ MOD_INC_USE_COUNT;
+
+ return OK;
+}
+
+/* dp83815_close - close a device, and reclaim resources */
+static int
+dp83815_close (struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ struct dp83815_priv* priv = dev->priv;
+
+ /* Stop the Tx/Rx */
+ /* Do we need to do this ??? */
+ DP_REG32_WRITE (DP_CR, (DP_CR_TXD | DP_CR_RXD));
+
+ /* Restore factory ethernet address */
+ dp83815_mac_address_set (iobase, priv->hw_mac_addr);
+
+ /* Uninstall the interrupt vector */
+ free_irq (dev->irq, dev);
+
+ /* Free the Tx and Rx queues */
+ dp83815_queue_delete (&priv->tx_queue);
+ dp83815_queue_delete (&priv->rx_queue);
+
+ /* Decrement module reference count */
+ MOD_DEC_USE_COUNT;
+
+ return OK;
+}
+
+/*
+ * dp83815_start_xmit - transmit an ethernet packet.
+ *
+ * This routine writes to a tx descriptor, sets the ownership bit of the
+ * CMDSTS, and signals the chip
+ */
+static int
+dp83815_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ u32 cmdsts;
+ virt_addr tx_desc;
+ struct net_device_stats *stats_p;
+
+ if (skb->len > ETH_MAX_PKT_SIZE)
+ return ERROR;
+
+ tx_desc = dp83815_tx_desc_get(dev);
+ if (tx_desc == NULL)
+ {
+ netif_stop_queue(dev);
+ DP_REG32_SET (DP_IMR, DP_IMR_TXOK | DP_IMR_TXIDLE);
+ tx_desc = dp83815_tx_desc_get (dev);
+ }
+
+ stats_p = &((struct dp83815_priv *)(dev->priv))->stats;
+
+ /* Update tx_desc to point to SKB data, set CMDSTS, and signal the chip */
+ if (tx_desc != NULL)
+ {
+ /* Reclaim SKBs from the TX queue */
+ if (DP_DESC_SKBPTR_GET (tx_desc))
+ dp83815_tx_skb_reclaim (dev, tx_desc);
+
+ /* update statistics of the previous transmit */
+ cmdsts = DP_DESC_CMDSTS_XLATE_GET (tx_desc);
+ if (cmdsts & DP_DESC_CMDSTS_TX_ERRORS)
+ {
+ stats_p->tx_errors++;
+
+ /* Update individual counters */
+
+ stats_p->collisions += DP_DESC_CMDSTS_TX_COLLISIONS_GET(cmdsts);
+
+ if (cmdsts & DP_DESC_CMDSTS_TX_TXA) /* tx aborted */
+ stats_p->tx_packets--;
+
+ if (cmdsts & DP_DESC_CMDSTS_TX_TFU) /* fifo errors */
+ stats_p->tx_fifo_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_TX_CRS) /* lost carrier */
+ stats_p->tx_carrier_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_TX_OWC) /* out of window collisions */
+ stats_p->tx_window_errors++;
+ }
+
+ /* Update the descriptor */
+
+ DP_DESC_BUFPTR_XLATE_SET (tx_desc, skb->data);
+ DP_DESC_SKBPTR_SET (tx_desc, (u32)skb);
+ DP_DESC_CMDSTS_XLATE_SET (tx_desc, DP_DESC_CMDSTS_OWN|skb->len);
+
+ dev->trans_start = jiffies;
+ DP_REG32_SET (DP_CR, DP_CR_TXE);
+ DP_DEBUG (DP_DEBUG_TX,
+ (KERN_INFO "Tx: tx_desc=0x%x ", (u32)tx_desc));
+ stats_p->tx_packets++;
+ } else
+ stats_p->tx_dropped++;
+
+ return OK;
+}
+
+/*
+ * dp83815_start_receive - receive the data from a Rx Queue descriptor
+ *
+ * This routine receives the data from Rx queue as long as it gets a valid
+ * rx_descriptor and resets the descriptor's CMDSTS field back to the Buffer
+ * size, and updates the BUFPTR and SKBPTR fields to the newly allocated SKB.
+ */
+static int
+dp83815_start_receive (struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ u32 cmdsts;
+ int len;
+ bool do_copy;
+ virt_addr rx_desc;
+ struct sk_buff *cur_skb;
+ struct sk_buff *new_skb;
+ struct sk_buff *rx_skb;
+ struct net_device_stats *stats_p;
+
+ stats_p = &((struct dp83815_priv *)(dev->priv))->stats;
+
+ for (rx_desc = dp83815_rx_desc_get(dev); (rx_desc != NULL); rx_desc = dp83815_rx_desc_get(dev))
+ {
+ DP_DEBUG (DP_DEBUG_RX,
+ (KERN_INFO "Rx: rx_desc=0x%x, CMDSTS = 0x%x",
+ (u32)rx_desc, DP_DESC_CMDSTS_XLATE_GET(rx_desc)));
+
+ cmdsts = DP_DESC_CMDSTS_XLATE_GET (rx_desc);
+
+ /* Send the packet to the stack if no errors */
+ if ((cmdsts & DP_DESC_CMDSTS_RX_ERRORS) == 0)
+ {
+ len = (cmdsts & DP_DESC_CMDSTS_SIZE) - ETH_CRC_LEN;
+ if (len > 0)
+ {
+ /*
+ * Allocate a new SKB
+ * small data packets less than DP_RX_COPY_THRESHOLD are copied
+ * into the new SKB, other allocate one to replace the current SKB.
+ */
+ if (len < DP_RX_COPY_THRESHOLD)
+ {
+ do_copy = TRUE;
+ new_skb = alloc_skb (len + 2, GFP_ATOMIC);
+ } else {
+ do_copy = FALSE;
+ new_skb = alloc_skb (ETH_MAX_PKT_SIZE, GFP_ATOMIC);
+ }
+
+ if (new_skb)
+ {
+ cur_skb = (struct sk_buff *) DP_DESC_SKBPTR_GET (rx_desc);
+
+ if (do_copy)
+ {
+ /* Copy data from current SKB and send the new SKB up */
+ rx_skb = new_skb;
+ skb_reserve (rx_skb, 2);
+ memcpy (skb_put(rx_skb, len), cur_skb->data, len);
+ } else {
+ /* Replace the the current SKB with the new SKB */
+ rx_skb = cur_skb;
+ DP_DESC_BUFPTR_XLATE_SET (rx_desc, new_skb->data);
+ DP_DESC_SKBPTR_SET (rx_desc, (u32) new_skb);
+ (void) skb_put(rx_skb, len);
+ }
+
+ /* update the SKB and set it up */
+ rx_skb->dev = dev;
+ rx_skb->protocol = eth_type_trans (rx_skb, dev);
+
+ netif_rx (rx_skb);
+
+ dev->last_rx = jiffies;
+ stats_p->rx_packets++;
+ } else
+ stats_p->rx_dropped++; /* no resources */
+ if (cmdsts & DP_DESC_CMDSTS_RX_DEST_MC)
+ stats_p->multicast++;
+ }
+ else /* code to deal with packets who's length is <= 0 */
+ /* this case should not happen but somehow, it happens */
+ {
+ stats_p->rx_errors++; /* bad packet */
+
+ /* Update individual counters */
+ if (cmdsts & (DP_DESC_CMDSTS_RX_RUNT | DP_DESC_CMDSTS_RX_LONG))
+ stats_p->rx_length_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_CRCE)
+ stats_p->rx_crc_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_FAE)
+ stats_p->rx_frame_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_RXO)
+ stats_p->rx_fifo_errors++;
+ }
+ }
+ else
+ {
+ stats_p->rx_errors++; /* bad packet */
+
+ /* Update individual counters */
+ if (cmdsts & (DP_DESC_CMDSTS_RX_RUNT | DP_DESC_CMDSTS_RX_LONG))
+ stats_p->rx_length_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_CRCE)
+ stats_p->rx_crc_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_FAE)
+ stats_p->rx_frame_errors++;
+
+ if (cmdsts & DP_DESC_CMDSTS_RX_RXO)
+ stats_p->rx_fifo_errors++;
+ }
+
+ /* Cleanup the descriptor and make available for reception */
+ DP_DESC_CMDSTS_XLATE_SET (rx_desc, ETH_MAX_PKT_SIZE);
+ DP_REG32_SET (DP_CR, DP_CR_RXE);
+ }
+ return OK;
+}
+
+/* dp83815_get_stats - get current device statistics */
+static struct net_device_stats *
+dp83815_get_stats (struct net_device *dev)
+{
+ return &((struct dp83815_priv *)(dev->priv))->stats;
+}
+
+/* dp83815_set_multicast_list - sets multicast, & promiscuous mode */
+static void
+dp83815_set_multicast_list (struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ u16 hash_table[32];
+ u32 rfcr_flags;
+ int i;
+ struct dev_mc_list * mc_list;
+
+ /* default RFCR mode */
+ rfcr_flags = DP_RFCR_APM | DP_RFCR_AAB | DP_RFCR_RFEN;
+
+ /* Setup promiscuous mode */
+ if (dev->flags & IFF_PROMISC)
+ {
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "IFF_PROMISC\n"));
+ rfcr_flags = (DP_RFCR_AAU | DP_RFCR_AAM | DP_RFCR_AAB |
+ DP_RFCR_RFEN);
+ } else if (dev->flags & IFF_ALLMULTI)
+ {
+ /* Receive all multicast packets */
+ DP_DEBUG (DP_DEBUG_OPEN, (KERN_INFO "IFF_ALLMULTI\n"));
+ rfcr_flags |= DP_RFCR_AAM;
+ } else
+ {
+ /* Setup to receive programmed multicast packets */
+ memset (hash_table, 0, 32);
+ for (i=0, mc_list=dev->mc_list; mc_list && i < dev->mc_count; i++, mc_list = mc_list->next)
+ {
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "mc_addr=%p\n", mc_list->dmi_addr));
+ set_bit (dp83815_crc((char *)mc_list->dmi_addr) & 0x1ff, hash_table);
+ }
+
+ /* install the hash table */
+ for (i=0; i<32; i++)
+ {
+ DP_REG32_WRITE (DP_RFCR, DP_RFCR_RFADDR_FMEM_LO + i*2);
+ DP_REG32_WRITE (DP_RFDR, (u32) hash_table[i]);
+ }
+
+ rfcr_flags |= DP_RFCR_MHEN;
+ }
+
+ DP_REG32_WRITE (DP_RFCR, 0);
+ DP_REG32_WRITE (DP_RFCR, rfcr_flags);
+ DP_DEBUG (DP_DEBUG_OPEN,
+ (KERN_INFO "MC Setup RFCR flags=0x%x\n", rfcr_flags));
+
+ return;
+}
+
+/* dp83815_crc - computer CRC for hash table entries */
+static int
+dp83815_crc (char * mc_addr)
+{
+ u32 crc;
+ u8 cur_byte;
+ u8 msb;
+ u8 byte, bit;
+
+ crc = ~0;
+ for (byte=0; byte<6; byte++)
+ {
+ cur_byte = *mc_addr++;
+ for (bit=0; bit<8; bit++)
+ {
+ msb = crc >> 31;
+ crc <<= 1;
+ if (msb ^ (cur_byte & 1))
+ {
+ crc ^= DP_POLYNOMIAL;
+ crc |= 1;
+ }
+ cur_byte >>= 1;
+ }
+ }
+ crc >>= 23;
+
+ return (crc);
+}
+
+/* dp83815_ioctl - handle driver specific ioctls */
+static int
+dp83815_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ return -EOPNOTSUPP;
+}
+
+/* dp83815_interrupt - handle the interrupts */
+static void
+dp83815_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device * dev = dev_id;
+ u16 iobase = dev->base_addr;
+ u32 reg_isr;
+
+ reg_isr = DP_REG32_READ (DP_ISR);
+
+ DP_DEBUG (DP_DEBUG_IOCTL,
+ (KERN_INFO "%s: intr_status=0x%x\n", dev->name,
+ reg_isr));
+
+ if (reg_isr & DP_ISR_RXOK)
+ dp83815_start_receive (dev);
+
+ /* The only place where these bits should be tested for is if
+ * we turned them on ourselves (out of buffers)
+ */
+ //if (reg_isr & (DP_ISR_TXOK | DP_ISR_TXIDLE))
+ if (netif_queue_stopped(dev) && (reg_isr & (DP_ISR_TXOK | DP_ISR_TXIDLE)))
+ {
+ DP_REG32_CLR (DP_IMR, (DP_IMR_TXOK|DP_IMR_TXIDLE));
+ printk("dp83815_interrupt: making transmitter non-idle\n");
+ netif_wake_queue(dev);
+ }
+}
+
+/* dp83815_mac_address_set - set the ethernet address */
+static void
+dp83815_mac_address_set (u32 iobase, char *mac_addr)
+{
+ u16 * mac_addr_ptr;
+ int i;
+
+ for (i=0, mac_addr_ptr = (u16 *)mac_addr; i<3; i++, mac_addr_ptr++)
+ {
+ DP_REG32_WRITE (DP_RFCR, DP_RFCR_RFADDR_PMATCH1 + i*2);
+ DP_REG32_WRITE (DP_RFDR, CPU_TO_BUS_SWAP_16 (*mac_addr_ptr));
+ }
+}
+
+/* dp83815_mac_address_get - get the ethernet address */
+static void
+dp83815_mac_address_get (u32 iobase, char *mac_addr)
+{
+ u16 * mac_addr_ptr;
+ int i;
+
+ for (i=0, mac_addr_ptr = (u16*)mac_addr; i<3; i++, mac_addr_ptr++)
+ {
+ DP_REG32_WRITE (DP_RFCR, DP_RFCR_RFADDR_PMATCH1 + i*2);
+ *mac_addr_ptr = BUS_TO_CPU_SWAP_16 (DP_REG32_READ (DP_RFDR));
+ }
+}
+
+/* dp83815_dev_reset - soft reset DP83815 */
+static status
+dp83815_dev_reset (u32 iobase)
+{
+ int timeout = 2000;
+ DP_REG32_WRITE (DP_CR, DP_CR_RST);
+ while ((timeout -= 5) > 0)
+ {
+ if ((DP_REG32_READ (DP_CR) & DP_CR_RST) == 0)
+ { /* Wait until bit clears */
+ DP_REG32_WRITE (DP_PTSCR, 0x04); /* Restore registers from EEROM */
+ udelay (2000);
+ /* Software reset of the controller has been successful. Reset the
+ * internal PHY Registers as well
+ */
+ DP_REG32_WRITE (DP_BMCR, DP_BMCR_RESET);
+
+ /* Wait awhile and check to see if it has cleared */
+ udelay (2000);
+ if ((DP_REG32_READ (DP_BMCR) & DP_BMCR_RESET) == DP_BMCR_RESET)
+ { /* Bad */
+ return ERROR;
+ }
+ return (OK);
+ }
+ udelay (5);
+ }
+ return ERROR;
+}
+
+/*
+ * dp83815_queue_create - create a circular queue of descriptors
+ *
+ * This routine allocates a descriptor buffer array aligned on a word
+ * boundary, initializes and links the array to make a circular queue.
+ */
+static status
+dp83815_queue_create (struct dp83815_queue *q, int count, int qtype)
+{
+ virt_addr desc_addr;
+ int i;
+ struct sk_buff *skb;
+
+ /* allocate the desc buffer array */
+ q->qbuf = (virt_addr) kmalloc (DP_QUEUE_ELE_SIZE * count + DP_ALIGN, GFP_DMA);
+ if (q->qbuf == (virt_addr) NULL)
+ return ERROR;
+
+ memset ((char *)q->qbuf, 0, DP_QUEUE_ELE_SIZE * count + DP_ALIGN);
+
+ /* Adjust alignment and Initialize queue data */
+ q->cur_desc_addr =
+ q->first_desc_addr =
+ (virt_addr)(((u32)q->qbuf + DP_ALIGN) & ~(DP_ALIGN - 1));
+ q->last_desc_addr = q->first_desc_addr + ((count -1) * DP_QUEUE_ELE_SIZE);
+ q->count = count;
+
+ /* Initialize each buffer descriptor, and link them into circular queue */
+ for (i=0, desc_addr=q->first_desc_addr; i<count;
+ i++, desc_addr+=DP_QUEUE_ELE_SIZE)
+ {
+ DP_DESC_LNK_XLATE_SET (desc_addr, desc_addr + DP_QUEUE_ELE_SIZE);
+
+ /* Update the size, BUFPTR, and SKBPTR fields for RX descriptors */
+ if (qtype == DP_QUEUE_TYPE_RX)
+ {
+ skb = alloc_skb (ETH_MAX_PKT_SIZE, GFP_ATOMIC);
+ if (skb == NULL)
+ {
+ dp83815_queue_delete (q);
+ return (ERROR);
+ }
+ DP_DESC_CMDSTS_XLATE_SET (desc_addr, ETH_MAX_PKT_SIZE);
+ DP_DESC_BUFPTR_XLATE_SET (desc_addr, skb->data);
+ DP_DESC_SKBPTR_SET (desc_addr, (u32) skb);
+ }
+ }
+ /* Make the queue circular */
+ DP_DESC_LNK_XLATE_SET (q->last_desc_addr, q->first_desc_addr);
+
+ return OK;
+}
+
+/* dp83815_queue_delete - frees an allocated descriptor queue */
+static status
+dp83815_queue_delete (struct dp83815_queue *q)
+{
+ int i;
+ virt_addr desc_addr;
+ struct sk_buff *skb;
+
+ /* Free all SKBs in the queue */
+ for (i=0, desc_addr=q->first_desc_addr;
+ (i < q->count);
+ i++, desc_addr += DP_QUEUE_ELE_SIZE)
+ {
+ skb = (struct sk_buff *) DP_DESC_SKBPTR_GET (desc_addr);
+ if (skb != NULL)
+ dev_kfree_skb (skb);
+ }
+
+ /* Free the queue buffer */
+ kfree ((char *)q->qbuf);
+
+ return (OK);
+}
+
+/*
+ * dp83815_tx_desc_get - get a valid transmit descriptor
+ *
+ * This routine returns the current descriptor from the tx_queue if driver is
+ * the owner, else returns NULL
+ */
+static virt_addr
+dp83815_tx_desc_get (struct net_device *dev)
+{
+ struct dp83815_queue * q;
+ virt_addr desc_addr = NULL;
+
+ q = &((struct dp83815_priv *)(dev->priv))->tx_queue;
+
+ /* Check if we own the descriptor */
+ if ((DP_DESC_CMDSTS_XLATE_GET (q->cur_desc_addr) & DP_DESC_CMDSTS_OWN) == 0)
+ {
+ desc_addr = q->cur_desc_addr;
+ DP_QUEUE_ELE_NEXT (q); /* Move to the next element */
+ }
+
+ return desc_addr;
+}
+
+/* dp83815_tx_skb_reclaim - reclaim SKBs in transmitted descriptors */
+static void
+dp83815_tx_skb_reclaim (struct net_device *dev, virt_addr desc_addr)
+{
+ struct sk_buff * skb;
+ struct dp83815_queue * q;
+
+ /* Reclaim buffers from all descriptors we own. */
+ q = &((struct dp83815_priv *)(dev->priv))->tx_queue;
+ while (((DP_DESC_CMDSTS_XLATE_GET(desc_addr) & DP_DESC_CMDSTS_OWN) == 0) &&
+ ((skb=(struct sk_buff *) DP_DESC_SKBPTR_GET(desc_addr)) != NULL))
+ {
+ dev_kfree_skb (skb);
+ DP_DESC_SKBPTR_SET (desc_addr, 0);
+ desc_addr = DP_QUEUE_ELE_NEXT_GET (q, desc_addr);
+ }
+}
+
+/*
+ * dp83815_rx_desc_get - get a valid receive descriptor
+ *
+ * This routine returns the current descriptor from the rx_queue if driver is
+ * the owner, else returns NULL
+ */
+static virt_addr
+dp83815_rx_desc_get (struct net_device *dev)
+{
+ struct dp83815_queue * q;
+ virt_addr desc_addr = NULL;
+
+ q = &((struct dp83815_priv *)(dev->priv))->rx_queue;
+
+ /* Check if we own the descriptor */
+ if (DP_DESC_CMDSTS_XLATE_GET (q->cur_desc_addr) & DP_DESC_CMDSTS_OWN)
+ {
+ desc_addr = q->cur_desc_addr;
+ DP_QUEUE_ELE_NEXT(q); /* Move to the next element */
+ }
+
+ return desc_addr;
+}
+
+/* dp83815_phy_setup - reset and setup the PHY device */
+static status
+dp83815_phy_setup (struct net_device *dev)
+{
+ u32 iobase = dev->base_addr;
+ u32 dp_cfg_val;
+ u16 phy_status;
+ u16 timeout;
+
+ dp_cfg_val = (DP_CFG_PESEL | /* parity error detect */
+ DP_CFG_ANEG_SEL_ALL_XD | /* negotiate 10/100 full/half */
+ DP_CFG_PAUSE_ADV | /* pause capable */
+ DP_CFG_PINT_ACEN | /* phy intr auto clear */
+ 0x00040000); /* phy config */
+
+ DP_REG32_WRITE (DP_CFG, dp_cfg_val | DP_CFG_PHY_RST);
+ udelay (500);
+
+ DP_REG32_WRITE (DP_CFG, dp_cfg_val);
+ for (timeout=10000; timeout; timeout--)
+ {
+ if (DP_REG32_READ (DP_CFG) & DP_CFG_ANEG_DN)
+ break;
+ udelay (500);
+ }
+
+ if (timeout == 0)
+ {
+ DP_DEBUG (DP_DEBUG_ANEG, (KERN_INFO "Phy Autonegotiate Failed\n"));
+ return (ERROR);
+ }
+ DP_REG32_WRITE (DP_PHY_PAGE, DP_PHY_PAGE_VAL);
+ DP_REG32_WRITE (DP_PHYCR, DP_PHYCR_PMDCSR_VAL);
+ DP_REG32_WRITE (DP_PHY_TDATA, DP_PHY_TDATA_VAL);
+ DP_REG32_WRITE (DP_PHY_DSPCFG, DP_PHY_DSPCFG_VAL);
+ DP_REG32_WRITE (DP_PHY_SDCFG, DP_PHY_SDCFG_VAL);
+ DP_REG32_WRITE (DP_PHY_PAGE, (u16) 0x0000);
+
+ phy_status = DP_REG16_READ (DP_PHYSTS);
+
+ /* Flag is set for full duplex mode, else cleared */
+
+ if (phy_status & DP_PHYSTS_FDX)
+ dp_full_duplex = TRUE;
+ else
+ dp_full_duplex = FALSE;
+
+ printk (KERN_INFO "%s: speed=%d duplex=%s link=%s\n",
+ dev->name,
+ (phy_status & DP_PHYSTS_SPEED_10) ? 10 : 100,
+ (phy_status & DP_PHYSTS_FDX)? "full" : "half",
+ (phy_status & DP_PHYSTS_LNK_VALID) ? "up" : "down");
+
+ return (OK);
+}
+
+#if 1
+/* swap_16 - swap a 16 bit value between little endian & big endian byteorder */
+static u16 swap_16 (u16 us)
+{
+ return ((us << 8) & 0xff00) | ((us >> 8) & 0x00ff);
+}
+#endif
+
+#if 0 /* Not used */
+/* swap_32 - swap a 32 bit value between little endian & big endian byteorder */
+static u32 swap_32 (u32 ui)
+{
+ return ((swap_16 (ui & 0x0000ffff) << 16) | swap_16 (ui >> 16));
+}
+#endif
+
+/* io_read_16 - read the 16 bit value stored at given io address */
+static u16 io_read_16 (u16 io_port)
+{
+ return inw (io_port);
+}
+
+#if 0 /* Not used */
+/* io_write_16 - write the 16 bit data at given io address */
+static void io_write_16 (u16 io_port, u16 data)
+{
+ outw (data, io_port);
+}
+#endif
+
+/* io_read_32 - read the 32 bit value stored at given io address*/
+static u32 io_read_32 (u16 io_port)
+{
+ return inl (io_port);
+}
+
+/* io_write_32 - write the 32 bit data at given io address */
+static void io_write_32 (u16 io_port, u32 data)
+{
+ outl (data, io_port);
+}
+
+#if (DRV_DEBUG > 0)
+/* dp83815_desc_info - print info on descriptors
+ *
+ * This routine displays values of the elements of dp83815_queue;
+ * if option is -1, prints info on all the descs and their field vals;
+ * and in all other cases prints info on the specified descriptor.
+ */
+
+static void dp83815_desc_info (struct dp83815_queue * q, int option)
+{
+ virt_addr desc_addr;
+ u32 i;
+
+ /* Display info header */
+ printk ( KERN_DEBUG "dp83815_desc_info(): q=0x%x, "
+ "first_desc_addr=0x%x, last_desc_addr=0x%x cur_desc_addr=0x%x\n",
+ (u32)q, (u32)q->first_desc_addr,
+ (u32)q->last_desc_addr, (u32)q->cur_desc_addr);
+
+ /* Print requested element info */
+ switch (option)
+ {
+ case -1: /* all elements */
+ desc_addr = q->first_desc_addr;
+ for (i=0; i<q->count; i++)
+ {
+ printk (KERN_DEBUG "desc_addr=0x%x link=0x%x "
+ "cmdsts=0x%x bufptr=0x%x\n",
+ (u32)desc_addr, DP_DESC_LNK_GET (desc_addr),
+ DP_DESC_CMDSTS_GET (desc_addr),
+ DP_DESC_BUFPTR_GET (desc_addr));
+ desc_addr += DP_QUEUE_ELE_SIZE;
+ }
+ break;
+
+ default: /* a specific element */
+ if (option > q->count)
+ {
+ printk (KERN_DEBUG "Can't print info for ele=%d when count=%d\n",
+ option, q->count);
+ } else
+ {
+ desc_addr = q->first_desc_addr + (DP_QUEUE_ELE_SIZE * (option - 1));
+ printk (KERN_DEBUG "ele=%d desc_addr=0x%x link=0x%x "
+ "cmdsts=0x%x bufptr=0x%x\n",
+ option, (u32)desc_addr, DP_DESC_LNK_GET (desc_addr),
+ DP_DESC_CMDSTS_GET (desc_addr),
+ DP_DESC_BUFPTR_GET (desc_addr));
+ }
+ }
+}
+
+
+/* dp83815_regs_info - prints values of registers */
+static void dp83815_regs_info (u16 iobase)
+{
+ printk (KERN_INFO "dp(0x%x): CFG=0x%x IMR=0x%x IER=0x%x\n",
+ iobase, DP_REG32_READ (DP_CFG), DP_REG32_READ (DP_IMR),
+ DP_REG32_READ (DP_IER));
+ printk (KERN_INFO " ++ TXDP=0x%x TXCFG=0x%x RXDP=0x%x RXCFG=0x%x\n",
+ DP_REG32_READ (DP_TXDP), DP_REG32_READ (DP_TXCFG),
+ DP_REG32_READ (DP_RXDP), DP_REG32_READ (DP_RXCFG));
+}
+#endif /* (DRV_DEBUG > 0) */
+
+static void __devexit dp83815_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+
+ if (!dev) {
+ printk (KERN_ERR "bug! dp83815_remove_one called without net_device\n");
+ return;
+ }
+
+ unregister_netdev (dev);
+ release_region (dev->base_addr, DP83815_PCI_IO_SIZE);
+ kfree (dev);
+}
+
+
+static struct pci_driver dp83815_driver = {
+ name: "dp83815",
+ probe: dp83815_probe,
+ remove: dp83815_remove_one,
+ id_table: dp83815_ids,
+};
+
+
+static int __init
+dp83815_init(void)
+{
+ return pci_module_init(&dp83815_driver);
+}
+
+static void __exit
+dp83815_cleanup(void)
+{
+ pci_unregister_driver(&dp83815_driver);
+}
+
+module_init(dp83815_init);
+module_exit(dp83815_cleanup);
+
+
+/*
+ * Local variables:
+ * version-control: t
+ * kept-new-versions: 5
+ * End:
+ */
--- linux-2.4.0-test5/drivers/net/dp83815.h Sat Jul 29 01:09:55 2000
+++ linux/drivers/net/dp83815.h Fri Jul 28 21:40:45 2000
@@ -0,0 +1,636 @@
+/* dp83815.h -- National Semiconductor DP83815 Ethernet Controller Interface */
+/* Changes for the Rev C of DP83815 have been included */
+
+#ifndef __DP83815_H__
+#define __DP83815_H__
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#endif
+
+#define DP_DEV_NAME "National Semiconductor DP83815 PCI Ethernet"
+#define DP_DRV_NAME "dp83815"
+
+/* PCI Confiugration Registers */
+
+#undef PCI_VENDOR_ID_NS_83815
+#define PCI_VENDOR_ID_NS_83815 0x0020 /* DP83815 */
+
+#define DP83815_PCI_IO_SIZE 256
+
+/*
+ * Operational Registers:
+ * These registers are mapped either into PCI memory space or I/O space.
+ */
+
+/* MAC/BIU Registers */
+
+#define DP_CR 0x00 /* Command Register */
+#define DP_CFG 0x04 /* Configuration Register */
+#define DP_MEAR 0x08 /* EEPROM Access Register */
+#define DP_PTSCR 0x0C /* PCI Test Control Register */
+#define DP_ISR 0x10 /* Intr Status Register */
+#define DP_IMR 0x14 /* Intr Mask Register */
+#define DP_IER 0x18 /* Intr Enable Register */
+#define DP_TXDP 0x20 /* Tx Descriptor Pointer Register */
+#define DP_TXCFG 0x24 /* Tx Configuration Register */
+#define DP_RXDP 0x30 /* Rx Descriptor Pointer Register */
+#define DP_RXCFG 0x34 /* Rx Configuration Register */
+#define DP_WCSR 0x40 /* Wake on LAN Control/Status Register */
+#define DP_PCR 0x44 /* Pause Control/Status Register */
+#define DP_RFCR 0x48 /* Rx Filter/Match Control Register */
+#define DP_RFDR 0x4C /* Rx Filter/Match Data Register */
+#define DP_BRAR 0x50 /* Boot ROM Address */
+#define DP_BRDR 0x54 /* Boot ROM Data */
+#define DP_SRR 0x58 /* Silicon Revision Register (RO) */
+#define DP_MIBC 0x5C /* MIB Control Registor */
+#define DP_MIB 0x60 /* MIB Data Register Base (RO) */
+
+/* MIB Registers */
+
+#define DP_MIB_RX_PKT_ERR 0x60 /* Pkts recvd with errors */
+#define DP_MIB_RX_FCS_ERR 0x64 /* Pkts recvd with frame check seq errs */
+#define DP_MIB_RX_MISS_PKT 0x68 /* Pkts missed due to FIFO overruns*/
+#define DP_MIB_RX_FA_ERR 0x6C /* Pkts recvd with frame alignment errs */
+#define DP_MIB_RX_SYM_ERR 0x70 /* Pkts recvd with symbol errs */
+#define DP_MIB_RX_LONG_FRM 0x74 /* Pkts > 1518 bytes */
+#define DP_MIB_TXSQE_ERR 0x78 /* Loss of coll. heartbeat on Tx */
+
+/* Internal Phy Registers */
+
+#define DP_BMCR 0x80 /* Basic Mode Control Register */
+#define DP_BMSR 0x84 /* Basic Mode Status Register (RO) */
+#define DP_PHYIDR1 0x88 /* PHY Identifier Register #1 (RO) */
+#define DP_PHYIDR2 0x8C /* PHY Identifier Register #2 (RO) */
+#define DP_ANAR 0x90 /* Auto-Nego Advertisment Reg */
+#define DP_ANLPAR 0x94 /* Auto-Nego Link Partner Ability Reg */
+#define DP_ANER 0x98 /* Auto-Negotiation Expansion Reg */
+#define DP_ANNPTR 0x9C /* Auto-Negotiation Next Page TX */
+#define DP_PHYSTS 0xC0 /* PHY Status Register (RO) */
+#define DP_FCSCR 0xD0 /* False Carrier Sense Counter Reg */
+#define DP_RECR 0xD4 /* Recv Error Counter Register */
+#define DP_PHYCR 0xE4 /* PHY Control Register */
+#define DP_10BTSCR 0xE8 /* 10Base-TStatus/Control Reg */
+
+/* New Phy registers and their bit mask values for Rev 3 */
+
+#define DP_PHY_PAGE 0xCC /* */
+#define DP_PHY_DSPCFG 0xF4 /* */
+#define DP_PHY_SDCFG 0xF8 /* */
+#define DP_PHY_TDATA 0xFC /* */
+
+#define DP_PHY_PAGE_VAL (u16)0x0001 /* */
+#define DP_PHY_DSPCFG_VAL (u16)0x5040 /* Load/Kill C2 */
+#define DP_PHY_SDCFG_VAL (u16)0x008C /* Raise SD off, from 4 to C */
+#define DP_PHY_TDATA_VAL (u16)0x0000 /* Set value for C2 */
+#define DP_PHYCR_PMDCSR_VAL (u16)0x189C /* DC Speed = 01 */
+
+/*
+ * Command Register Bit Masks (DP_CR)
+ *
+ * This register is used for issuing commands to DP83815. A global software
+ * reset along with individual reset and enable/disable switches for
+ * transmitter and receiver are provided here.
+ */
+
+#define DP_CR_TXE 0x00000001 /* Transmit Enable */
+#define DP_CR_TXD 0x00000002 /* Transmit Disable */
+#define DP_CR_RXE 0x00000004 /* Receiver Enable */
+#define DP_CR_RXD 0x00000008 /* Receiver Disable */
+#define DP_CR_TXR 0x00000010 /* Transmit Reset */
+#define DP_CR_RXR 0x00000020 /* Receiver Reset */
+#define DP_CR_SWI 0x00000080 /* Software Interrupt */
+#define DP_CR_RST 0x00000100 /* Reset */
+
+/*
+ * Configuration and Media Status Register Bit Masks (DP_CFG)
+ *
+ * This register allows configuration of a various device and phy options,
+ * and provide phy status information.
+ */
+
+#define DP_CFG_BEM (u32)0x00000001 /* Big Endian Mode (BM xfers) */
+#define DP_CFG_BROM_DIS (u32)0x00000004 /* Disable Boot ROM interface */
+#define DP_CFG_PESEL (u32)0x00000008 /* Parity Err Det (BM xfer) */
+#define DP_CFG_EXD (u32)0x00000010 /* Excessv Deferl Tmr disbl */
+#define DP_CFG_POW (u32)0x00000020 /* Prog Out of Window Timer */
+#define DP_CFG_SB (u32)0x00000040 /* Single Back-off */
+#define DP_CFG_REQALG (u32)0x00000080 /* PCI Bus Request Algorithm */
+#define DP_CFG_EUPHCOMP (u32)0x00000100 /* DP83810 Descriptor Compat */
+#define DP_CFG_PHY_DIS (u32)0x00000200 /* Disable internal Phy */
+#define DP_CFG_PHY_RST (u32)0x00000400 /* Reset internal Phy */
+#define DP_CFG_ANEG_SEL (u32)0x0000E000 /* Auto-nego Sel - Mask */
+#define DP_CFG_ANEG_SEL_10_HD (u32)0x00000000 /* Force 10Mb Half duplex */
+#define DP_CFG_ANEG_SEL_100_HD (u32)0x00004000 /* Force 100Mb Half duplex */
+#define DP_CFG_ANEG_SEL_10_FD (u32)0x00008000 /* Force 10Mb Full duplex */
+#define DP_CFG_ANEG_SEL_100_FD (u32)0x0000C000 /* Force 100Mb Full duplex */
+#define DP_CFG_ANEG_SEL_10_XD (u32)0x00002000 /* Nego 10Mb Half/Full dplx */
+#define DP_CFG_ANEG_SEL_ALL_HD (u32)0x00006000 /* Nego 10/100 Half duplex */
+#define DP_CFG_ANEG_SEL_100_XD (u32)0x0000A000 /* Nego 100 Half/Full duplex */
+#define DP_CFG_ANEG_SEL_ALL_XD (u32)0x0000E000 /* Nego 10/100 Half/Full dplx*/
+#define DP_CFG_PAUSE_ADV (u32)0x00010000 /* Strap for pause capable */
+#define DP_CFG_PINT_ACEN (u32)0x00020000 /* Phy Intr Auto Clr Enable */
+#define DP_CFG_PHY_CFG (u32)0x00FC0000 /* Phy Configuration */
+#define DP_CFG_ANEG_DN (u32)0x08000000 /* Auto-negotiation Done */
+#define DP_CFG_POL (u32)0x10000000 /* 10Mb Polarity Indication */
+#define DP_CFG_FDUP (u32)0x20000000 /* Full Duplex */
+#define DP_CFG_SPEED100 (u32)0x40000000 /* Speed 100Mb */
+#define DP_CFG_LNKSTS (u32)0x80000000 /* Link status */
+
+/*
+ * EEPROM Access Register Bit Masks (DP_MEAR)
+ *
+ * Provides an interface for software access to the NMC9306 style EEPROM. The
+ * default values given assume that the EEDO line has a pullup resistor to
+ * VDD.
+ */
+
+#define DP_MEAR_EEDI (u32)0x00000001 /* EEPROM data in */
+#define DP_MEAR_EEDO (u32)0x00000002 /* EEPROM data out */
+#define DP_MEAR_EECLK (u32)0x00000004 /* EEPROM Serial Clock */
+#define DP_MEAR_EESEL (u32)0x00000008 /* EEPROM Chip Select */
+
+/* PCI Test Control Register Bit Masks (DP_PTSCR) */
+
+#define DP_PTSCR_EEBIST_FAIL (u32)0x00000001 /* EE BIST Fail Indication */
+#define DP_PTSCR_EEBIST_EN (u32)0x00000002 /* Enable EEPROM BIST */
+#define DP_PTSCR_EELOAD_EN (u32)0x00000004 /* Enable EEPROM Load */
+#define DP_PTSCR_RBIST_RXFFAIL (u32)0x00000008 /* RX Filter RAM BIST Fail */
+#define DP_PTSCR_RBIST_TXFAIL (u32)0x00000010 /* TX FiFO Fail */
+#define DP_PTSCR_RBIST_RXFAIL (u32)0x00000020 /* RX FIFO BIST Fail */
+#define DP_PTSCR_RBIST_ACT (u32)0x00000040 /* SRAM BIST Active*/
+#define DP_PTSCR_RBIST_EN (u32)0x00000080 /* SRAM BIST Enable */
+#define DP_PTSCR_RBIST_MODE (u32)0x00000100 /* SRAM BIST Mode */
+#define DP_PTSCR_RBIST_CLKD (u32)0x00000200 /* SRAM BIST Clock */
+#define DP_PTSCR_RBIST_RST (u32)0x00000400 /* SRAM BIST Reset */
+#define DP_PTSCR_RESVD (u32)0x00001000 /* Reserved -- Must be 1 */
+
+/*
+ * Interrupt Status Register Bit Masks (DP_ISR)
+ *
+ * Indicates the source of an interrupt when the INTA pin goes active.
+ * Enabling the corresponding bit in the IMR allows bits in this reg to produce
+ * an interrupt. ISR reflects all pending iterrupts regardless of the status
+ * of the corresponding mask bit in the IMR.
+ */
+
+#define DP_ISR_RXOK (u32)0x00000001 /* Rx OK */
+#define DP_ISR_RXDESC (u32)0x00000002 /* Rx Descriptor */
+#define DP_ISR_RXERR (u32)0x00000004 /* Rx packet Error */
+#define DP_ISR_RXEARLY (u32)0x00000008 /* Rx Early Threshold */
+#define DP_ISR_RXIDLE (u32)0x00000010 /* Rx Idle */
+#define DP_ISR_RXORN (u32)0x00000020 /* Rx Overrun */
+#define DP_ISR_TXOK (u32)0x00000040 /* Tx Packet OK */
+#define DP_ISR_TXDESC (u32)0x00000080 /* Tx Descriptor */
+#define DP_ISR_TXERR (u32)0x00000100 /* Tx Packet Error */
+#define DP_ISR_TXIDLE (u32)0x00000200 /* Tx Idle */
+#define DP_ISR_TXURN (u32)0x00000400 /* Tx Underrun */
+#define DP_ISR_MIB (u32)0x00000800 /* MIB Service */
+#define DP_ISR_SWI (u32)0x00001000 /* Software Interrupt */
+#define DP_ISR_PME (u32)0x00002000 /* Power Management Event */
+#define DP_ISR_PHY (u32)0x00004000 /* Phy Interrupt */
+#define DP_ISR_HIBERR (u32)0x00008000 /* High Bits error set */
+#define DP_ISR_RXSOVR (u32)0x00010000 /* Rx Status FIFO Overrun */
+#define DP_ISR_RTABT (u32)0x00100000 /* Recieved Target Abort */
+#define DP_ISR_RMABT (u32)0x00200000 /* Recieved Master Abort */
+#define DP_ISR_SSERR (u32)0x00400000 /* Signaled System Error */
+#define DP_ISR_DPERR (u32)0x00800000 /* Detected Parity Error */
+#define DP_ISR_RXRCMP (u32)0x01000000 /* Receive Reset Complete */
+#define DP_ISR_TXRCMP (u32)0x02000000 /* Transmit Reset Complete */
+
+/*
+ * Interrupt Mask Register Bit Masks (DP_IMR)
+ *
+ * Interrupts are enabled by setting the appropriate bit-mask.
+ */
+
+#define DP_IMR_RXOK (u32)0x00000001 /* Rx ok */
+#define DP_IMR_RXDESC (u32)0x00000002 /* Rx Descriptor */
+#define DP_IMR_RXERR (u32)0x00000004 /* Rx packet Error */
+#define DP_IMR_RXEARLY (u32)0x00000008 /* Rx Early Threshold */
+#define DP_IMR_RXIDLE (u32)0x00000010 /* Rx Idle */
+#define DP_IMR_RXORN (u32)0x00000020 /* Rx Overrun */
+#define DP_IMR_TXOK (u32)0x00000040 /* Tx Packet Ok */
+#define DP_IMR_TXDESC (u32)0x00000080 /* Tx Descriptor */
+#define DP_IMR_TXERR (u32)0x00000100 /* Tx Packet Error */
+#define DP_IMR_TXIDLE (u32)0x00000200 /* Tx Idle */
+#define DP_IMR_TXURN (u32)0x00000400 /* Tx Underrun */
+#define DP_IMR_MIB (u32)0x00000800 /* MIB Service */
+#define DP_IMR_SWI (u32)0x00001000 /* Software Interrupt */
+#define DP_IMR_PME (u32)0x00002000 /* Power Management Event */
+#define DP_IMR_PHY (u32)0x00004000 /* Phy Interrupt */
+#define DP_IMR_HIERR (u32)0x00008000 /* High Bits error set */
+#define DP_IMR_RXSOVR (u32)0x00010000 /* Rx Status FIFO Overrun */
+#define DP_IMR_RTABT (u32)0x00100000 /* Recieved Target Abort */
+#define DP_IMR_RMABT (u32)0x00200000 /* Recieved Master Abort */
+#define DP_IMR_SSERR (u32)0x00400000 /* Signaled System Error */
+#define DP_IMR_DPERR (u32)0x00800000 /* Detected Parity Error */
+#define DP_IMR_RXRCMP (u32)0x01000000 /* Receive Reset Complete */
+#define DP_IMR_TXRCMP (u32)0x02000000 /* Transmit Reset Complete */
+
+/*
+ * Interrupt Enable Register Bit Masks (DP_IER)
+ *
+ * Enable or disable DP chip interrupts
+ */
+
+#define DP_IER_IE (u32)0x00000001 /* Interrupt Enable */
+#define DP_IER_ID (u32)0x00000000 /* Interrupt Disable */
+
+/* Transmit descriptor Pointer Register Bit Mask (DP_TXDP) */
+
+#define DP_TXDP_MSK (u32)0xFFFFFFFE /* Transmit Descriptor Ptr */
+
+/* Transmit Configuration Register Bit Masks (DP_TXCFG) */
+
+#define DP_TXCFG_DRTH (u32)0x0000003F /* Tx Drain Threshold */
+#define DP_TXCFG_FLTH (u32)0x00003F00 /* Tx Fill Threshold */
+#define DP_TXCFG_MXDMA (u32)0x00700000 /* Max DMA Burst Size */
+#define DP_TXCFG_MXDMA_1 (u32)0x00100000 /* 1 32-bit word */
+#define DP_TXCFG_MXDMA_2 (u32)0x00200000 /* 2 32-bit words */
+#define DP_TXCFG_MXDMA_4 (u32)0x00300000 /* 4 32-bit words */
+#define DP_TXCFG_MXDMA_8 (u32)0x00400000 /* 8 32-bit words */
+#define DP_TXCFG_MXDMA_16 (u32)0x00500000 /* 16 32-bit words */
+#define DP_TXCFG_MXDMA_32 (u32)0x00600000 /* 32 32-bit words */
+#define DP_TXCFG_MXDMA_64 (u32)0x00700000 /* 64 32-bit words */
+#define DP_TXCFG_MXDMA_128 (u32)0x00000000 /* 128 32-bit words */
+#define DP_TXCFG_IFG (u32)0x0C000000 /* Interframe gap Time */
+#define DP_TXCFG_ATP (u32)0x10000000 /* Automatic Transmit Pad */
+#define DP_TXCFG_MLB (u32)0x20000000 /* MAC Loopback */
+#define DP_TXCFG_HBI (u32)0x40000000 /* HeartBeat Ignore */
+#define DP_TXCFG_CSI (u32)0x80000000 /* Carrier Sense Ignore */
+
+#define DP_TXCFG_DRTH_SET(X) ((X) & DP_TXCFG_DRTH)
+#define DP_TXCFG_FLTH_SET(X) (((X) << 8) & DP_TXCFG_FLTH)
+
+/* Recieve Descriptor Pointer Register Bit Mask (DP_RXDP) */
+
+#define DP_RXDP_MSK (u32)0xFFFFFFFC /* Receive Descriptor Ptr */
+
+/* Recieve Configuration Register Bit Masks (DP_RXCFG) */
+
+#define DP_RXCFG_DRTH (u32)0x0000003E /* Rx Drain Threshold */
+#define DP_RXCFG_MXDMA (u32)0x00700000 /* Max DMA Burst size */
+#define DP_RXCFG_MXDMA_1 (u32)0x00100000 /* 1 32-bit words */
+#define DP_RXCFG_MXDMA_2 (u32)0x00200000 /* 2 32-bit words */
+#define DP_RXCFG_MXDMA_4 (u32)0x00300000 /* 4 32-bit words */
+#define DP_RXCFG_MXDMA_8 (u32)0x00400000 /* 8 32-bit words */
+#define DP_RXCFG_MXDMA_16 (u32)0x00500000 /* 16 32-bit words */
+#define DP_RXCFG_MXDMA_32 (u32)0x00600000 /* 32 32-bit words */
+#define DP_RXCFG_MXDMA_64 (u32)0x00700000 /* 64 32-bit words */
+#define DP_RXCFG_MXDMA_128 (u32)0x00000000 /* 128 32-bit words */
+#define DP_RXCFG_ALP (u32)0x08000000 /* Accept Long Packets */
+#define DP_RXCFG_ATX (u32)0x10000000 /* Accept transmit packets */
+#define DP_RXCFG_ARP (u32)0x40000000 /* Accept Runt Packets */
+#define DP_RXCFG_AEP (u32)0x80000000 /* Accept Errored Packets */
+
+#define DP_RXCFG_DRTH_SET(X) ((X) & DP_RXCFG_DRTH)
+
+/*
+ * Wake Command/status Register Bit Masks (DP_WCSR)
+ *
+ * It is used to configure/control and monitor DP83815 Wake Od LAN Logic
+ * The Wake On LAN logic is used to monitor the incoming packet stream while
+ * in a low-power state, and provide a wake event to the system if desired
+ * packet type, contents, or Link change are detected.
+ */
+
+#define DP_WCSR_WKPHY (u32)0x00000001 /* Wake on Phy Interrupt */
+#define DP_WCSR_WKUCP (u32)0x00000002 /* Wake on unicast */
+#define DP_WCSR_WKMCP (u32)0x00000004 /* Wake on Multicast */
+#define DP_WCSR_WKBCP (u32)0x00000008 /* Wake on Broadcast */
+#define DP_WCSR_WKARP (u32)0x00000010 /* Wake on ARP */
+#define DP_WCSR_WKPAT0 (u32)0x00000020 /* Wake on Pattern 0 match */
+#define DP_WCSR_WKPAT1 (u32)0x00000040 /* Wake on Pattern 1 match */
+#define DP_WCSR_WKPAT2 (u32)0x00000080 /* Wake on Pattern 2 match */
+#define DP_WCSR_WKPAT3 (u32)0x00000100 /* Wake on Pattern 3 match */
+#define DP_WCSR_WKMAG (u32)0x00000200 /* Wake on Magic Packet */
+#define DP_WCSR_MPSOE (u32)0x00000400 /* Magic Packet SecureOn Enbl */
+#define DP_WCSR_SOHACK (u32)0x00200000 /* SecureOn Hack Attempt */
+#define DP_WCSR_PHYINT (u32)0x00400000 /* Phy Interrupt */
+#define DP_WCSR_UCASTR (u32)0x00800000 /* Unicast Recieved */
+#define DP_WCSR_MCASTR (u32)0x01000000 /* Multicast Recieved */
+#define DP_WCSR_BCASTR (u32)0x02000000 /* Broadcast Recieved */
+#define DP_WCSR_ARPR (u32)0x04000000 /* ARP Recieved */
+#define DP_WCSR_PATM0 (u32)0x08000000 /* Pattern 0 match */
+#define DP_WCSR_PATM1 (u32)0x10000000 /* Pattern 1 match */
+#define DP_WCSR_PATM2 (u32)0x20000000 /* Pattern 2 match */
+#define DP_WCSR_PATM3 (u32)0x40000000 /* Pattern 3 match */
+#define DP_WCSR_MPR (u32)0x80000000 /* Magic Packet Recieved */
+
+/*
+ * Pause Control/Status Register Bit Masks (DP_PCR)
+ *
+ * It is used to control and monitor the DP 83815 Pause Frame reception logic
+ * The Pause frame reception logic is used to accept 802.3x Pause frames,
+ * extract the pause length value, and initiate a TXMAV pause interval of the
+ * specified number of slot times.
+ */
+
+#define DP_PCR_PAUSE_CNT (u32)0x0000FFFF /* Pause Counter value */
+#define DP_PCR_MLD_EN (u32)0x00010000 /* Manual Load Enable */
+#define DP_PCR_PSNEG (u32)0x00200000 /* Pause negotiated */
+#define DP_PCR_PS_RCVD (u32)0x00400000 /* Pause frame recieved */
+#define DP_PCR_PS_ACT (u32)0x00800000 /* Pause Active */
+#define DP_PCR_PS_DA (u32)0x20000000 /* Pause on DA */
+#define DP_PCR_PS_MCAST (u32)0x40000000 /* Pause on Multicast */
+#define DP_PCR_PSEN (u32)0x80000000 /* Pause Enable */
+
+/*
+ * Recieve Filter/Match Control Register Bit Masks (DP_RFCR)
+ *
+ * It is used to control and configure the DP83815 Recieve Filter Control logic
+ * The RFC logic is used to configure destination address filtering of incoming
+ * packets.
+ */
+
+#define DP_RFCR_RFADDR (u32)0x000003FF /* Rx Filter Extended RegAdd */
+#define DP_RFCR_RFADDR_PMATCH1 (u32)0x00000000 /* Perfect Match octets 1-0 */
+#define DP_RFCR_RFADDR_PMATCH2 (u32)0x00000002 /* Perfect Match octets 3-2 */
+#define DP_RFCR_RFADDR_PMATCH3 (u32)0x00000004 /* Perfect Match octets 5-4 */
+#define DP_RFCR_RFADDR_PCOUNT1 (u32)0x00000006 /* Pattern Count 1-0 */
+#define DP_RFCR_RFADDR_PCOUNT2 (u32)0x00000008 /* Pattern Count 3-2 */
+#define DP_RFCR_RFADDR_SOPAS1 (u32)0x0000000A /* SecureOn Password 1-0 */
+#define DP_RFCR_RFADDR_SOPAS2 (u32)0x0000000C /* SecureOn Password 3-2 */
+#define DP_RFCR_RFADDR_SOPAS3 (u32)0x0000000E /* SecureOn Password 5-4 */
+#define DP_RFCR_RFADDR_FMEM_LO (u32)0x00000200 /* Rx filter memory start */
+#define DP_RFCR_RFADDR_FMEM_HI (u32)0x000003FE /* Rx filter memory end */
+#define DP_RFCR_ULM (u32)0x00080000 /* U/L bit Mask */
+#define DP_RFCR_UHEN (u32)0x00100000 /* Unicast Hash Enable */
+#define DP_RFCR_MHEN (u32)0x00200000 /* Multicast Hash Enable */
+#define DP_RFCR_AARP (u32)0x00400000 /* Accept ARP Packets */
+#define DP_RFCR_APAT (u32)0x07800000 /* Accept On Pattern Match */
+#define DP_RFCR_APM (u32)0x08000000 /* Accept on Perfect match */
+#define DP_RFCR_AAU (u32)0x10000000 /* Accept All Unicast */
+#define DP_RFCR_AAM (u32)0x20000000 /* Accept All Multicast */
+#define DP_RFCR_AAB (u32)0x40000000 /* Accept All Broadcast */
+#define DP_RFCR_RFEN (u32)0x80000000 /* Rx Filter Enable */
+
+/*
+ * Recieve Filter/Match Data Register Bit Masks (DP_RFDR)
+ *
+ * This register is used to read and write internal recieve filter registers,
+ * the pattern buffer memory and the hash table memory.
+ */
+
+#define DP_RFDR_RFDATA (u32)0x0000FFFF /* Recieve Filter data */
+#define DP_RFDR_BMASK (u32)0x00030000 /* Byte Mask */
+
+/* Boot ROM Address Register Bit Masks (DP_BRAR) */
+
+#define DP_BRAR_ADDR (u32)0x0000FFFF /* Boot ROM Address */
+#define DP_BRAR_AUTOINC (u32)0x80000000 /* Auto-Increment */
+
+/* Boot ROM Data Register Bit Masks (DP_BRDR) */
+
+#define DP_BRDR_DATA (u32)0xFFFFFFFF /* Boot ROM Data */
+
+/* Silicon Revision Register Bit Masks (DP_SRR) */
+
+#define DP_SRR_MIN (u32)0x000000FF /* Minor Revision Level */
+#define DP_SRR_MAJ (u32)0x0000FF00 /* Major Revision Level */
+#define DP_SRR_MAJ_SHF 8 /* Shift bits */
+
+/*
+ * Management Information Base Control Register Bit Masks (DP_MIBC)
+ *
+ * It is used to control access to the statistics block and the warning bits
+ * and to control the collection of management info statistics.
+ */
+
+#define DP_MIBC_WRN (u32)0x00000001 /* Warning Tst Indicator (RO) */
+#define DP_MIBC_FRZ (u32)0x00000002 /* Freeze All Counters */
+#define DP_MIBC_ACLR (u32)0x00000004 /* Clear all Counters */
+#define DP_MIBC_MIBS (u32)0x00000008 /* MIB Counter Strobe (TEST) */
+
+/* BMCR - (Internal Phy) Basic Mode Control Register */
+
+#define DP_BMCR_COL_TST (u16)0x0080 /* Collision Test */
+#define DP_BMCR_HDX (u16)0x0000 /* Half duplex mode */
+#define DP_BMCR_FDX (u16)0x0100 /* Full duplex mode */
+#define DP_BMCR_ANEG_RES (u16)0x0200 /* Restart Auto negotiation */
+#define DP_BMCR_ISOLATE (u16)0x0400 /* Isolate */
+#define DP_BMCR_PWRDWN (u16)0x0800 /* Power Down */
+#define DP_BMCR_ANEG_EN (u16)0x3100 /* Auto Negotiation Enable */
+#define DP_BMCR_SPD_100 (u16)0x2000 /* Speed Select 100Mbps */
+#define DP_BMCR_SPD_10 (u16)0x0000 /* Speed Select 100Mbps */
+#define DP_BMCR_LOOP (u16)0x4000 /* Loopback */
+#define DP_BMCR_RESET (u16)0xB100 /* Reset */
+
+/* BMSR - (Internal Phy) Basic Mode Status Register */
+
+#define DP_BMSR_XREG_ABLE (u16)0x0001 /* Extended Register Capability */
+#define DP_BMSR_JABR_DET (u16)0x0002 /* Jabber Detected */
+#define DP_BMSR_LNK_VALID (u16)0x0004 /* Valid Link Status */
+#define DP_BMSR_AN_ABLE (u16)0x0008 /* Auto-Neg Ability */
+#define DP_BMSR_REM_FLT (u16)0x0010 /* Remote Fault Detected */
+#define DP_BMSR_AN_DONE (u16)0x0020 /* Auto Nego Complete */
+#define DP_BMSR_PRS_ABLE (u16)0x0040 /* Preamble Supr Capable */
+#define DP_BMSR_10_HD_ABLE (u16)0x0800 /* 10BASE-T Half Duplex Capable */
+#define DP_BMSR_10_FD_ABLE (u16)0x1000 /* 10BASE-T Full Duplex Capable */
+#define DP_BMSR_100_HD_ABLE (u16)0x2000 /* 100BASE-TX Half Duplex Capable */
+#define DP_BMSR_100_FD_ABLE (u16)0x4000 /* 100BASE-TX Full Duplex Capable */
+#define DP_BMSR_100T4_ABLE (u16)0x8000 /* 100BASE -T4 Capable */
+
+/* PHY Identifier Register #1 */
+
+#define DP_PHYIDR1_OUI_MSB (u16)0xFFFF /* OUI Most significant Bits */
+
+/* PHY Identifier Register #2 */
+
+#define DP_PHYIDR2_MDL_REV (u16)0x000F /* Model Revision number */
+#define DP_PHYIDR2_VNDR_MDL (u16)0x03F0 /* Vendor Model Number */
+#define DP_PHYIDR2_OUI_LSB (u16)0xFC00 /* OUI Last Significant Bits */
+
+/*
+ * Auto-Negotiation Advertisement Register
+ *
+ * Contains the advertised abilities of this device as they will be transmitted
+ * to its link partner during Auto-Negotiation.
+ */
+
+#define DP_ANAR_SEL (u16)0x001F /* Protocol Selection Bits */
+#define DP_ANAR_10T (u16)0x0020 /* 10BASE-T Support */
+#define DP_ANAR_10_FD (u16)0x0040 /* 10BASE-T Full Duplex Support */
+#define DP_ANAR_TX (u16)0x0080 /* 100BASE-TX Support */
+#define DP_ANAR_TX_FD (u16)0x0100 /* 100BASE-TX Full Duplex Support */
+#define DP_ANAR_T4 (u16)0x0200 /* 100BASE-T4 Support */
+#define DP_ANAR_PAUSE (u16)0x0400 /* Pause */
+#define DP_ANAR_RF (u16)0x2000 /* Remote Fault */
+#define DP_ANAR_NP (u16)0x8000 /* Next Page Indication */
+
+/*
+ * Auto-Negotiation Link Partner Ability Register
+ *
+ * Contains the advertised abilities of the Link Partner as recieved during
+ * Auto Negotiation. The content changes after the successful autonegotiation
+ * if Next-Pages are supported.
+ */
+
+#define DP_ANLPAR_SEL (u16)0x001F /* Protocol Selection Bits */
+#define DP_ANLPAR_10T (u16)0x0020 /* 10BASE-T Support */
+#define DP_ANLPAR_10_FD (u16)0x0040 /* 10BASE-T Full Duplex */
+#define DP_ANLPAR_TX (u16)0x0080 /* 100BASE-TX Support */
+#define DP_ANLPAR_TX_FD (u16)0x0100 /* 100BASE-TX Full Duplex */
+#define DP_ANLPAR_T4 (u16)0x0200 /* 100BASE-T4 Support */
+#define DP_ANLPAR_RF (u16)0x2000 /* Remote Fault */
+#define DP_ANLPAR_ACK (u16)0x4000 /* Acknowledge */
+#define DP_ANLPAR_NP (u16)0x8000 /* Next Page Indication */
+
+/*
+ * Auto-Negotiation Expansion Register
+ *
+ * contains additional Local device and Link Partner status info
+ */
+
+#define DP_ANER_LP_AN_ABLE (u16)0x0001 /* Link Partner Auto Neg Able */
+#define DP_ANER_PAGE_RX (u16)0x0002 /* Link Code Word Page Recvd */
+#define DP_ANER_NP_ABLE (u16)0x0004 /* Next Page Able */
+#define DP_ANER_LP_NP_ABLE (u16)0x0008 /* Link Partner NextPage Able */
+#define DP_ANER_PDF (u16)0x0010 /* Parallel Detection Fault */
+
+/*
+ * Auto-Negotiation Next page Transmit Register
+ *
+ * contains the next page Info sent by this device to its Link Partner
+ * during Auto-Negotiation
+ */
+
+#define DP_ANNPTR_CODE (u16)0x07FF /* Code Field */
+#define DP_ANNPTR_TOG_TX (u16)0x0800 /* Toggle */
+#define DP_ANNPTR_ACK2 (u16)0x1000 /* Acknowledge2 */
+#define DP_ANNPTR_MP (u16)0x2000 /* Message Page */
+#define DP_ANNPTR_NP (u16)0x8000 /* Next Page Indication */
+
+/*
+ * PHY Status Register
+ *
+ * provides a single location within the register set for quick access to
+ * commonly accessed information
+ */
+
+#define DP_PHYSTS_LNK_VALID (u16)0x0001 /* Valid Link */
+#define DP_PHYSTS_SPEED_10 (u16)0x0002 /* 10 Mbps Mode */
+#define DP_PHYSTS_FDX (u16)0x0004 /* Full Duplex Mode */
+#define DP_PHYSTS_LOOP (u16)0x0008 /* Loopback Enabled */
+#define DP_PHYSTS_ANEG_DONE (u16)0x0010 /* Auto-Neg Complete */
+#define DP_PHYSTS_JABBER (u16)0x0020 /* Jabbler Detected */
+#define DP_PHYSTS_REM_FAULT (u16)0x0040 /* Remote Fault Detected */
+#define DP_PHYSTS_MII_INTR (u16)0x0080 /* MII Interrupt Pending */
+#define DP_PHYSTS_LCWP_RX (u16)0x0100 /* Link Code Word Page Rx'd */
+#define DP_PHYSTS_DSCRMBL_LCK (u16)0x0200 /* 100TX Descrambler Lock */
+#define DP_PHYSTS_SIG_DET (u16)0x0400 /* 100TX Uncond Signal Detect */
+#define DP_PHYSTS_FCSL (u16)0x0800 /* False Carrier Sense Latch */
+#define DP_PHYSTS_POL_INV (u16)0x1000 /* Polarity status */
+#define DP_PHYSTS_RX_ERR_LATCH (u16)0x2000 /* Received error latch */
+
+/*
+ * False carrier Sense Counter Register
+ *
+ * provides info required to implement the "FalseCarriers" attribute within
+ * the MAJ managed object class of Clause 30 of the IEEE 802.3u specification.
+ */
+
+#define DP_FCSCR_FCSCNT (u16)0x00FF /* False Carrier Event Counter */
+
+/*
+ * Receiver Error Counter Register
+ *
+ * provides info required to implement the "SymbolErrorDuringCarrier" attribute
+ * within the PHY managed object class of Clause 30 of the IEEE 802.3u
+ * specification.
+ */
+
+#define DP_RECR_RXERCNT (u16)0x00FF /* RX_ER Counter*/
+
+/* 100Mb/s PCS Configuration and Status Register */
+
+#define DP_PCSR_NRZI_BYP (u16)0x0004 /* NRZI Bypass Enable */
+#define DP_PCSR_FRC_100_OK (u16)0x0020 /* Force 100Mb/s Good Link */
+#define DP_PCSR_SD_OPT (u16)0x0100 /* Signal Detect Option */
+#define DP_PCSR_SD_F_B (u16)0x0200 /* Signal Detect Force */
+#define DP_PCSR_TQ_EN (u16)0x0400 /* 100Mbs True Quite Mode En */
+#define DP_PCSR_FREE_CLK (u16)0x0800 /* Receive Clock */
+#define DP_PCSR_BYP_4B5B (u16)0x1000 /* Bypass 4B/5B Encoding */
+
+/* PHY Control Register */
+
+#define DP_PHYCR_PHYADDR (u16)0x001F /* PHY Address */
+#define DP_PHYCR_LED_CFG (u16)0x0060 /* LED Configuration */
+#define DP_PHYCR_LED_CFG_10_HI (u16)0x0000 /* Speed10 HIGH */
+#define DP_PHYCR_LED_CFG_10 (u16)0x0020 /* Speed10 selected */
+#define DP_PHYCR_LED_CFG_DPLXHI (u16)0x0040 /* DPLX active HIGH */
+#define DP_PHYCR_LED_CFG_DPLX (u16)0x0060 /* DPLX selected */
+#define DP_PHYCR_PAUSE_PASS (u16)0x0080 /* Pause Compare Pass */
+#define DP_PHYCR_BP_STRETCH (u16)0x0100 /* Bypass LED Stretch*/
+#define DP_PHYCR_BIST_START (u16)0x0200 /* BIST Start */
+#define DP_PHYCR_BIST_PASS (u16)0x0400 /* BIST Pass */
+#define DP_PHYCR_PSR_15 (u16)0x0800 /* BIST Sequence Sel PSR15 (PSR9) */
+
+/* 10Base-T Status/Control Register(10BTSCR) */
+
+#define DP_10BTSCR_JABR_DIS (u16)0x0001 /* Jabber Disable */
+#define DP_10BTSCR_HB_DIS (u16)0x0002 /* Heartbeat Disable */
+#define DP_10BTSCR_LOW_SQL (u16)0x0004 /* Reduced Sqyelch Enable */
+#define DP_10BTSCR_AUTOPOL_DIS (u16)0x0008 /* Auto Polarity Disable */
+#define DP_10BTSCR_POL (u16)0x0010 /* 10Mb Polarity Status */
+#define DP_10BTSCR_FRC_POL_COR (u16)0x0020 /* Force 10Mb Polarity Correction */
+#define DP_10BTSCR_FRC_10 (u16)0x0040 /* Force 10Mb Good Link */
+#define DP_10BTSCR_LP_DIS (u16)0x0080 /* Normal Link Pulse Disable */
+#define DP_10BTSCR_LB10_DIS (u16)0x0100 /* 10Base-T Loopback Disable */
+
+
+/*
+ * Transmit and receive descriptors
+ *
+ * DP83815 uses the same descriptor layout for both transmit and receive
+ * descriptors.
+ */
+
+#define DP_DESC_SIZE 0x0C /* 3 words */
+
+/* Descriptor Layout */
+
+#define DP_DESC_LNK 0x00 /* Link field offset */
+#define DP_DESC_CMDSTS 0x04 /* Command & Status offset */
+#define DP_DESC_BUFPTR 0x08 /* Buffer pointer offset */
+
+/* DP_DESC_CMDSTS - Descriptor Command and Status Definitions */
+
+#define DP_DESC_CMDSTS_SIZE (u32)0x00000FFF /* Size of data in bytes */
+#define DP_DESC_CMDSTS_TX_CCNT (u32)0x000F0000 /* Collision Count */
+#define DP_DESC_CMDSTS_TX_EC (u32)0x00100000 /* Excessive Collisions */
+#define DP_DESC_CMDSTS_TX_OWC (u32)0x00200000 /* Out of window collns */
+#define DP_DESC_CMDSTS_TX_ED (u32)0x00400000 /* Excessive deferrals */
+#define DP_DESC_CMDSTS_TX_TD (u32)0x00800000 /* Transmit deferrals */
+#define DP_DESC_CMDSTS_TX_CRS (u32)0x01000000 /* Carrier sense lost */
+#define DP_DESC_CMDSTS_TX_TFU (u32)0x02000000 /* Tx FIFO underrun */
+#define DP_DESC_CMDSTS_TX_TXA (u32)0x04000000 /* Tx abort */
+#define DP_DESC_CMDSTS_RX_COL (u32)0x00010000 /* Collision */
+#define DP_DESC_CMDSTS_RX_LBP (u32)0x00020000 /* Loopback packet */
+#define DP_DESC_CMDSTS_RX_FAE (u32)0x00040000 /* Frame align error */
+#define DP_DESC_CMDSTS_RX_CRCE (u32)0x00080000 /* CRC error */
+#define DP_DESC_CMDSTS_RX_ISE (u32)0x00100000 /* Invalid symbol error */
+#define DP_DESC_CMDSTS_RX_RUNT (u32)0x00200000 /* Runt packet */
+#define DP_DESC_CMDSTS_RX_LONG (u32)0x00400000 /* Long packet */
+#define DP_DESC_CMDSTS_RX_DEST (u32)0x01800000 /* Destination Class */
+#define DP_DESC_CMDSTS_RX_DEST_REJ (u32)0x00000000 /* Packet Rejected */
+#define DP_DESC_CMDSTS_RX_DEST_UNI (u32)0x00800000 /* Unicast packet */
+#define DP_DESC_CMDSTS_RX_DEST_MC (u32)0x01000000 /* Multicast packet */
+#define DP_DESC_CMDSTS_RX_DEST_BC (u32)0x01800000 /* Broadcast packet */
+#define DP_DESC_CMDSTS_RX_RXO (u32)0x02000000 /* Receive overrun */
+#define DP_DESC_CMDSTS_RX_RXA (u32)0x04000000 /* Receive aborted */
+#define DP_DESC_CMDSTS_OK (u32)0x08000000 /* Packet OK */
+#define DP_DESC_CMDSTS_TX_SUPCRC (u32)0x10000000 /* Supress CRC */
+#define DP_DESC_CMDSTS_RX_INCCRC (u32)0x10000000 /* Include CRC */
+#define DP_DESC_CMDSTS_INTR (u32)0x20000000 /* Interrupt */
+#define DP_DESC_CMDSTS_MORE (u32)0x40000000 /* More descriptors */
+#define DP_DESC_CMDSTS_OWN (u32)0x80000000 /* Desc owner (consumer) */
+
+#define DP_DESC_CMDSTS_TX_COLLISIONS_GET(cmdsts) (((cmdsts) & DP_DESC_CMDSTS_TX_CCNT) >> 16)
+
+#define DP_DESC_CMDSTS_TX_ERRORS (DP_DESC_CMDSTS_TX_CCNT | DP_DESC_CMDSTS_TX_EC | DP_DESC_CMDSTS_TX_OWC | DP_DESC_CMDSTS_TX_ED | DP_DESC_CMDSTS_TX_CRS | DP_DESC_CMDSTS_TX_TFU | DP_DESC_CMDSTS_TX_TXA)
+
+#define DP_DESC_CMDSTS_RX_ERRORS (DP_DESC_CMDSTS_RX_RXA | DP_DESC_CMDSTS_RX_RXO | DP_DESC_CMDSTS_RX_LONG | DP_DESC_CMDSTS_RX_RUNT | DP_DESC_CMDSTS_RX_CRCE | DP_DESC_CMDSTS_RX_FAE)
+
+#endif /* __DP83815_H__ */
--- linux-2.4.0-test5/drivers/net/Config.in Thu Jun 29 10:14:00 2000
+++ linux/drivers/net/Config.in Fri Jul 28 18:45:52 2000
@@ -137,6 +137,7 @@
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
          tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
       fi
+ dep_tristate ' National Semiconductor DP83815 PCI support' CONFIG_DP83815 $CONFIG_PCI
       dep_tristate ' EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
          if [ "$CONFIG_EEPRO100" = "y" -o "$CONFIG_EEPRO100" = "m" ]; then
--- linux-2.4.0-test5/drivers/net/Makefile Mon Jun 19 13:30:57 2000
+++ linux/drivers/net/Makefile Fri Jul 28 18:45:52 2000
@@ -197,6 +202,7 @@
 obj-$(CONFIG_ES3210) += es3210.o 8390.o
 obj-$(CONFIG_LNE390) += lne390.o 8390.o
 obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_DP83815) += dp83815.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
--- linux-2.4.0-test5/Documentation/Configure.help Thu Jul 27 16:40:57 2000
+++ linux/Documentation/Configure.help Fri Jul 28 18:45:52 2000
@@ -8901,6 +8901,16 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
+National DP83815 PCI support
+CONFIG_DP83815
+ National provided DP83815 Ethernet chip driver.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called dp83815.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt as well as
+ Documentation/networking/net-modules.txt.
+
 EtherExpress PRO/100 support
 CONFIG_EEPRO100
   If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jul 31 2000 - 21:00:29 EST