From 36383205d6df4700f06902424cb7c3ba42698e8d Mon Sep 17 00:00:00 2001 From: Dobrica Pavlinusic Date: Mon, 14 May 2007 00:51:43 -0500 Subject: [PATCH] include upstream ip1000a driver version 2.09f --- drivers/net/Config.in | 1 + drivers/net/Makefile | 5 + drivers/net/ip1000a/.ipg.o.flags | 3 + drivers/net/ip1000a/.ipg_main.o.flags | 3 + drivers/net/ip1000a/Makefile | 6 + drivers/net/ip1000a/Makefile.orig | 93 + drivers/net/ip1000a/PhyParam.h | 59 + drivers/net/ip1000a/ipg.h | 181 ++ drivers/net/ip1000a/ipg.o | Bin 0 -> 21681 bytes drivers/net/ip1000a/ipg_constants.h | 563 ++++ drivers/net/ip1000a/ipg_macros.h | 462 +++ drivers/net/ip1000a/ipg_main.c | 4289 +++++++++++++++++++++++++ drivers/net/ip1000a/ipg_main.o | Bin 0 -> 21588 bytes drivers/net/ip1000a/ipg_structs.h | 176 + drivers/net/ip1000a/ipg_tune.h | 350 ++ drivers/net/ip1000a/make2.2.sh | 1 + drivers/net/ip1000a/make2.2mod.sh | 1 + drivers/net/ip1000a/readme.txt | 141 + 18 files changed, 6334 insertions(+) create mode 100644 drivers/net/ip1000a/.ipg.o.flags create mode 100644 drivers/net/ip1000a/.ipg_main.o.flags create mode 100644 drivers/net/ip1000a/Makefile create mode 100644 drivers/net/ip1000a/Makefile.orig create mode 100644 drivers/net/ip1000a/PhyParam.h create mode 100644 drivers/net/ip1000a/ipg.h create mode 100644 drivers/net/ip1000a/ipg.o create mode 100644 drivers/net/ip1000a/ipg_constants.h create mode 100644 drivers/net/ip1000a/ipg_macros.h create mode 100644 drivers/net/ip1000a/ipg_main.c create mode 100644 drivers/net/ip1000a/ipg_main.o create mode 100644 drivers/net/ip1000a/ipg_structs.h create mode 100644 drivers/net/ip1000a/ipg_tune.h create mode 100644 drivers/net/ip1000a/make2.2.sh create mode 100644 drivers/net/ip1000a/make2.2mod.sh create mode 100644 drivers/net/ip1000a/readme.txt diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 188fe42..21da023 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -259,6 +259,7 @@ dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACE if [ "$CONFIG_ACENIC" != "n" ]; then bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I fi +dep_tristate 'IC PLUS IP1000 1000/100/10 based Ethernet support' CONFIG_IP1000A $CONFIG_PCI dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI dep_tristate 'Intel(R) PRO/1000 Gigabit Ethernet support' CONFIG_E1000 $CONFIG_PCI if [ "$CONFIG_E1000" != "n" ]; then diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 82f52fe..464cfc2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -31,6 +31,10 @@ ifeq ($(CONFIG_E1000),y) obj-y += e1000/e1000.o endif +ifeq ($(CONFIG_IP1000A),y) + obj-y += ip1000a/ipg.o +endif + ifeq ($(CONFIG_BONDING),y) obj-y += bonding/bonding.o endif @@ -53,6 +57,7 @@ subdir-$(CONFIG_SK98LIN) += sk98lin subdir-$(CONFIG_SKFP) += skfp subdir-$(CONFIG_E100) += e100 subdir-$(CONFIG_E1000) += e1000 +subdir-$(CONFIG_IP1000A) += ip1000a subdir-$(CONFIG_BONDING) += bonding # diff --git a/drivers/net/ip1000a/.ipg.o.flags b/drivers/net/ip1000a/.ipg.o.flags new file mode 100644 index 0000000..0396297 --- /dev/null +++ b/drivers/net/ip1000a/.ipg.o.flags @@ -0,0 +1,3 @@ +ifeq (ipg_main.o,$(strip $(subst $(comma),:,$(LDFLAGS) $(EXTRA_LDFLAGS) $(obj-y)))) +FILES_FLAGS_UP_TO_DATE += ipg.o +endif diff --git a/drivers/net/ip1000a/.ipg_main.o.flags b/drivers/net/ip1000a/.ipg_main.o.flags new file mode 100644 index 0000000..318bce9 --- /dev/null +++ b/drivers/net/ip1000a/.ipg_main.o.flags @@ -0,0 +1,3 @@ +ifeq (-D__KERNEL__ -I/rest/ppc/linux-2.4.34.4/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-builtin-sprintf -fomit-frame-pointer -I/rest/ppc/linux-2.4.34.4/arch/ppc -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring -nostdinc -iwithprefix include,$(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_ipg_main.o)))) +FILES_FLAGS_UP_TO_DATE += ipg_main.o +endif diff --git a/drivers/net/ip1000a/Makefile b/drivers/net/ip1000a/Makefile new file mode 100644 index 0000000..18f4740 --- /dev/null +++ b/drivers/net/ip1000a/Makefile @@ -0,0 +1,6 @@ +O_TARGET := ipg.o + +obj-y := ipg_main.o +obj-m := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff --git a/drivers/net/ip1000a/Makefile.orig b/drivers/net/ip1000a/Makefile.orig new file mode 100644 index 0000000..c91b384 --- /dev/null +++ b/drivers/net/ip1000a/Makefile.orig @@ -0,0 +1,93 @@ +# +# Makefile for IC Plus Ethernet Adapter driver for Linux +# Copyright (c) 2004 by IC Plus Corporation. +# +# +OBJS = ipg_main.o +TARGET = ipg.o +MAPPING_MODE= -DUSE_IO_OPS +#MAPPING_MODE= -DUSE_IO_OPS -DJUMBO_FRAME -DJUMBO_FRAME_SIZE_4K + +KernelVersion := $(shell uname -r) +KernelBuildDir := /lib/modules/$(KernelVersion)/build +kernelMisc := /lib/modules/$(KernelVersion)/kernel/drivers/net/ +kernelExtension := $(shell echo $(KernelVersion) | sed -ne 's/^2\.[567]\..*/k/p')o +kernelFlag26 := kernel2$(shell echo $(KernelVersion) | sed -ne 's/^2\.[6]\..*/6/p')x + + +#======================Makefile for kernel 2.2.x and 2.4.x====================== +ifneq ($(kernelFlag26),kernel26x) +CC = gcc +CFLAGS = -D__KERNEL__ -DMODULE -O -Wall -Wstrict-prototypes -I$(INCLUDEDIR) +EXTRA_CFLAGS := $(MAPPING_MODE) +EXTRA_CFLAGS := $(EXTRA_CFLAGS) -D_COMPAT_WITH_OLD_KERNEL + + +KernelSrcPath := /lib/modules/$(shell uname -r)/build \ + /usr/src/linux-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ + /usr/src/kernel-headers-$(shell uname -r) \ + /usr/src/kernel-source-$(shell uname -r) \ + /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ + /usr/src/linux +FindDir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) +KernelSrcPath := $(foreach dir, $(KernelSrcPath), $(FindDir)) +KernelSrc := $(firstword $(KernelSrcPath)) + +# Support Linux software VLAN +#EXTRA_CFLAGS := $(EXTRA_CFLAGS) -DCONFIG_VLAN_8021Q + +#EXTRA_CFLAGS := $(EXTRA_CFLAGS) -DEXTRA_STATS +#DEBUG_FLAGS = -O -g -DALTA_DEBUG +K_VER=$(shell uname -r) +INCLUDEDIR=$(shell if [ -e /usr/src/linux-$(K_VER)/include ]; \ + then echo "/usr/src/linux-$(K_VER)/include"; \ + elif [ -e /usr/src/linux-2.4/include ]; \ + then echo "/usr/src/linux-2.4/include"; \ + elif [ -e /usr/src/linux/include ]; \ + then echo "/usr/src/linux/include"; \ + else echo "/usr/include"; fi) +# +# Old kernel need to configure modversions.h +# +#EXTRA_CFLAGS := $(EXTRA_CFLAGS) \ +# $(shell if [ -e $(INCLUDEDIR)/linux/modversions.h ]; \ +# then echo -DCONFIG_MODVERSIONS; fi) + +CFLAGS+=$(shell [ -f $(KernelSrc)/include/linux/modversions.h ] && \ + echo "-DMODVERSIONS -include $(KernelSrc)/include/linux/modversions.h") + +$(TARGET): $(OBJS) + $(LD) -r -o $@ $(OBJS) +# +# Dependency to create object file. +# +all: $(TARGET) +# +# +# Common make rules +# +%.o:%.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(DEBUG_FLAGS) -c -o $@ $< +endif + + +#===========================Makefile for kernel 2.6.x=========================== +ifeq ($(kernelFlag26),kernel26x) +EXTRA_CFLAGS+=$(MAPPING_MODE) + +all: + $(MAKE) -C $(KernelBuildDir) SUBDIRS=$(PWD) modules + +install: + install -m 644 -c ipg.$(kernelExtension) $(kernelMisc) + +ipg-objs:=$(OBJS) +obj-m+=$(TARGET) +endif + +#===========================Makefile common section============================ +# Delete existing object file +# +clean: + rm -f *.o *.ko *~ core* .dep* .*.d .*.cmd *.mod.c *.a *.s .*.flags diff --git a/drivers/net/ip1000a/PhyParam.h b/drivers/net/ip1000a/PhyParam.h new file mode 100644 index 0000000..b2a30b2 --- /dev/null +++ b/drivers/net/ip1000a/PhyParam.h @@ -0,0 +1,59 @@ +// PhyParam.h +//variable record -- index by leading revision/length +//Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN +unsigned short DefaultPhyParam[] = { + // 11/12/03 IP1000A v1-3 rev=0x40 + /*-------------------------------------------------------------------------- + (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2, + 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6, + 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700, + --------------------------------------------------------------------------*/ + // 12/17/03 IP1000A v1-4 rev=0x40 + (0x4000|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x41 + (0x4100|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x42 + (0x4200|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x43 + (0x4300|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x44 + (0x4400|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x45 + (0x4500|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x46 + (0x4600|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x47 + (0x4700|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x48 + (0x4800|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x49 + (0x4900|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x4A + (0x4A00|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x4B + (0x4B00|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x4C + (0x4C00|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x4D + (0x4D00|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + // 01/09/04 IP1000A v1-5 rev=0x4E + (0x4E00|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + 0x0000}; + + + diff --git a/drivers/net/ip1000a/ipg.h b/drivers/net/ip1000a/ipg.h new file mode 100644 index 0000000..557ef75 --- /dev/null +++ b/drivers/net/ip1000a/ipg.h @@ -0,0 +1,181 @@ +/* + * + * ipg.h + * + * Include file for Gigabit Ethernet device driver for Network + * Interface Cards (NICs) utilizing the Tamarack Microelectronics + * Inc. IPG Gigabit or Triple Speed Ethernet Media Access + * Controller. + * + * Craig Rich + * Sundance Technology, Inc. + * 1485 Saratoga Avenue + * Suite 200 + * San Jose, CA 95129 + * 408 873 4117 + * www.sundanceti.com + * craig_rich@sundanceti.com + * + * Rev Date Description + * -------------------------------------------------------------- + * 0.1 11/8/99 Initial revision work begins + * + * 0.2 12/1/99 Minor update to modversions.h inclusion. + * + * 0.3 12/30/99 Updates to fully comply with IPG spec. + * + * 0.4 4/24/00 Updates to allow for removal of FCS generation + * and verification. + * 0.5 8/15/00 Updates for MII PHY registers and fields. + * + * 0.6 8/31/00 Updates to change to using 64 bit data types + * + * 0.7 10/31/00 Added DDEBUG_MSG to allow for easy activation of + * individual DEBUG_MSGs. + * + * 0.8 11/06/00 Changed LastFreedRxBuff to LastRestoredRxBuff for + * clarity. + * + * 0.9 11/10/00 Changed Sundance DeviceID to 0x9020 + * + * 0.10 2/14/01 Changed "DROP_ON_ERRORS", breaking out Ethernet from + * TCP/IP errors. + * + * 0.11 3/16/01 Changed "IPG_FRAMESBETWEENTXCOMPLETES" to + * "IPG_FRAMESBETWEENTXDMACOMPLETES" since will + * be using TxDMAIndicate instead of TxIndicate to + * improve performance. Added TFDunavailCount and + * RFDlistendCount to aid in performance improvement. + * + * 0.12 3/22/01 Removed IPG_DROP_ON_RX_TCPIP_ERRORS. + * + * 0.13 3/23/01 Removed IPG_TXQUEUE_MARGIN. + * + * 0.14 3/30/01 Broke out sections into multiple files and added + * OS version specific detection and settings. + */ + + +/* + * Linux header utilization: + * + * config.h For PCI support, namely CONFIG_PCI macro. + * + * version.h For Linux kernel version detection. + * + * module.h For modularized driver support. + * + * kernel.h For 'printk'. + * + * pci.h PCI support, including ID, VENDOR, and CLASS + * standard definitions; PCI specific structures, + * including pci_dev struct. + * + * ioport.h I/O ports, check_region, request_region, + * release_region. + * + * errno.h Standard error numbers, e.g. ENODEV. + * + * asm/io.h For reading/writing I/O ports, and for virt_to_bus + * function. + * + * delay.h For milisecond delays. + * + * types.h For specific typedefs (i.e. u32, u16, u8). + * + * netdevice.h For device structure needed for network support. + * + * etherdevice.h For ethernet device support. + * + * init.h For __initfunc. + * + * skbuff.h Socket buffer (skbuff) definition. + * + * asm/bitops.h For test_and_set_bit, clear_bit functions. + * + * asm/spinlock.h For spin_lock_irqsave, spin_lock_irqrestore functions. + * + */ + + +#include +#include +#include + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) && defined(MODVERSIONS)) + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ + +#define DrvVer "2.09d" + +const char *version = +"ipg : "DrvVer" Written by Craig Rich, www.sundanceti.com\n"; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)) + char kernel_version[] = UTS_RELEASE; +#endif + +#if (defined(MODULE) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,1,15))) + MODULE_AUTHOR("IC Plus Corp. 2003 "); + MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver "DrvVer); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) + #define IPG_LINUX2_2 + #undef IPG_LINUX2_4 + + #define IPG_DEV_KFREE_SKB(skb) dev_kfree_skb(skb) + + #define IPG_HOST2BUS_MAP(addr) virt_to_bus(addr) + + #define IPG_PCI_RESOURCE_START(dev, bar) dev->base_address[bar] + + #define IPG_TX_NOTBUSY(dev) clear_bit(0,(void*)&dev->tbusy) + #define IPG_IS_TX_BUSY(dev) test_and_set_bit(0, (void*)&dev->tbusy) + + #define IPG_DEVICE_TYPE struct device + #define IPG_STATS_TYPE struct enet_statistics +#else + #undef IPG_LINUX2_2 + #define IPG_LINUX2_4 + + #define IPG_DEV_KFREE_SKB(skb) dev_kfree_skb_irq(skb) + + #define IPG_HOST2BUS_MAP(addr) addr + + #define IPG_PCI_RESOURCE_START(dev, bar) dev->resource[bar].start + + #define IPG_TX_NOTBUSY(dev) netif_wake_queue(dev) + #define IPG_IS_TX_BUSY(dev) netif_queue_stopped(dev) + + #define IPG_DEVICE_TYPE struct net_device + #define IPG_STATS_TYPE struct net_device_stats +#endif + +/* Order of the following includes is important, the following must + * appear first: + * ipg_constants.h + * ipg_tune.h + */ +#include "ipg_constants.h" +#include "ipg_tune.h" +#include "ipg_macros.h" +#include "ipg_structs.h" +#include "PhyParam.h" + +/* end ipg.h */ diff --git a/drivers/net/ip1000a/ipg.o b/drivers/net/ip1000a/ipg.o new file mode 100644 index 0000000000000000000000000000000000000000..912f2554a1ee63ddfe0bbbe7e3e6dd3cb679e1be GIT binary patch literal 21681 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 S!hyK+gj!>|6-U_yBmI9$h`{pz literal 0 HcmV?d00001 diff --git a/drivers/net/ip1000a/ipg_constants.h b/drivers/net/ip1000a/ipg_constants.h new file mode 100644 index 0000000..fbc0787 --- /dev/null +++ b/drivers/net/ip1000a/ipg_constants.h @@ -0,0 +1,563 @@ +/* + * + * ipg_constants.h + * + * Include file with non-tunable constants for Gigabit Ethernet + * device driver for Network Interface Cards (NICs) utilizing the + * Tamarack Microelectronics Inc. IPG Gigabit or Triple Speed + * Ethernet Media Access Controller. + * + * Craig Rich + * Sundance Technology, Inc. + * 1485 Saratoga Avenue + * Suite 200 + * San Jose, CA 95129 + * 408 873 4117 + * www.sundanceti.com + * craig_rich@sundanceti.com + * + * Rev Date Description + * -------------------------------------------------------------- + * 0.1 3/30/01 New file created from original ipg.h + * + * 0.2 8/13/01 Added GMII based PHY IDs and GMII_ID_1. + * + * 0.3 8/16/01 Added GMII_PHY_CONTROL_RESET. + */ + +/* GMII based PHY IDs */ +#define NS 0x2000 +#define MARVELL 0x0141 +#define ICPLUS_PHY 0x243 + +/* NIC Physical Layer Device MII register addresses. */ +#define MII_PHY_CONTROL 0x00 +#define MII_PHY_STATUS 0x01 +#define MII_PHY_IDENTIFIER_MSB 0x02 +#define MII_PHY_IDENTIFIER_LSB 0x03 +#define MII_PHY_AUTONEGADVERTISEMENT 0x04 +#define MII_PHY_AUTONEGLINKPARTABILITY 0x05 +#define MII_PHY_AUTONEGEXPANSION 0x06 +#define MII_PHY_AUTONEGNP_TRANSMIT 0x07 +#define MII_PHY_AUTONEGLP_RECEIVE_NP 0x08 +#define MII_PHY_EXTENDED_STATUS 0x0F + +/* NIC Physical Layer Device MII register fields. */ +#define MII_PHY_CONTROL_RESTARTAN 0x0200 +#define MII_PHY_SELECTORFIELD 0x001F +#define MII_PHY_SELECTOR_IEEE8023 0x0001 +#define MII_PHY_TECHABILITYFIELD 0x1FE0 +#define MII_PHY_TECHABILITY_10BT 0x0020 +#define MII_PHY_TECHABILITY_10BTFD 0x0040 +#define MII_PHY_TECHABILITY_100BTX 0x0080 +#define MII_PHY_TECHABILITY_100BTXFD 0x0100 +#define MII_PHY_TECHABILITY_100BT4 0x0200 +#define MII_PHY_TECHABILITY_PAUSE_FIELDS 0x0C00 +#define MII_PHY_TECHABILITY_PAUSE 0x0400 +#define MII_PHY_TECHABILITY_ASM_DIR 0x0800 +#define MII_PHY_TECHABILITY_RSVD2 0x1000 +#define MII_PHY_STATUS_AUTONEG_ABILITY 0x0008 + +/* NIC Physical Layer Device GMII register addresses. */ +#define GMII_PHY_CONTROL 0x00 +#define GMII_PHY_STATUS 0x01 +#define GMII_PHY_ID_1 0x02 +#define GMII_PHY_AUTONEGADVERTISEMENT 0x04 +#define GMII_PHY_AUTONEGLINKPARTABILITY 0x05 +#define GMII_PHY_AUTONEGEXPANSION 0x06 +#define GMII_PHY_AUTONEGNEXTPAGE 0x07 +#define GMII_PHY_AUTONEGLINKPARTNEXTPAGE 0x08 +#define GMII_PHY_EXTENDEDSTATUS 0x0F + +#define GMII_PHY_1000BASETCONTROL 0x09 +#define GMII_PHY_1000BASETSTATUS 0x0A + +/* GMII_PHY_1000 need to set to prefer master */ +#define GMII_PHY_1000BASETCONTROL_PreferMaster 0x0400 + +#define GMII_PHY_1000BASETCONTROL_FULL_DUPLEX 0x0200 +#define GMII_PHY_1000BASETCONTROL_HALF_DUPLEX 0x0100 +#define GMII_PHY_1000BASETSTATUS_FULL_DUPLEX 0x0800 +#define GMII_PHY_1000BASETSTATUS_HALF_DUPLEX 0x0400 + +/* NIC Physical Layer Device GMII register Fields. */ +#define GMII_PHY_CONTROL_RESET 0x8000 +#define GMII_PHY_CONTROL_FULL_DUPLEX 0x0100 +#define GMII_PHY_STATUS_AUTONEG_ABILITY 0x0008 +#define GMII_PHY_ADV_FULL_DUPLEX 0x0020 +#define GMII_PHY_ADV_HALF_DUPLEX 0x0040 +#define GMII_PHY_ADV_PAUSE 0x0180 +#define GMII_PHY_ADV_PAUSE_PS1 0x0080 +#define GMII_PHY_ADV_ASM_DIR_PS2 0x0100 + +/* NIC Physical Layer Device GMII constants. */ +#define GMII_PREAMBLE 0xFFFFFFFF +#define GMII_ST 0x1 +#define GMII_READ 0x2 +#define GMII_WRITE 0x1 +#define GMII_TA_READ_MASK 0x1 +#define GMII_TA_WRITE 0x2 + +/* PCI register addresses. */ +#define IPG_POWERMGMTCTRL 0x54 +#define IPG_POWERMGMTCAP 0x52 +#define IPG_NEXTITEMPTR 0x51 +#define IPG_CAPID 0x50 +#define IPG_MAXLAT 0x3F +#define IPG_MINGNT 0x3E +#define IPG_INTERRUPTPIN 0x3D +#define IPG_INTERRUPTLINE 0x3C +#define IPG_CAPPTR 0x34 +#define IPG_EXPROMBASEADDRESS 0x30 +#define IPG_SUBSYSTEMID 0x2E +#define IPG_SUBSYSTEMVENDORID 0x2C +#define IPG_MEMBASEADDRESS 0x14 +#define IPG_IOBASEADDRESS 0x10 +#define IPG_HEADERTYPE 0x0E +#define IPG_LATENCYTIMER 0x0D +#define IPG_CACHELINESIZE 0x0C +#define IPG_CLASSCODE 0x09 +#define IPG_REVISIONID 0x08 +#define IPG_CONFIGSTATUS 0x06 +#define IPG_CONFIGCOMMAND 0x04 +#define IPG_DEVICEID 0x02 +#define IPG_VENDORID 0x00 + +/* I/O register offsets. */ +#define IPG_DMACTRL 0x00 +#define IPG_RXDMASTATUS 0x08 /* RESERVED */ +#define IPG_TFDLISTPTR0 0x10 +#define IPG_TFDLISTPTR1 0x14 +#define IPG_TXDMABURSTTHRESH 0x18 +#define IPG_TXDMAURGENTTHRESH 0x19 +#define IPG_TXDMAPOLLPERIOD 0x1A +#define IPG_RFDLISTPTR0 0x1C +#define IPG_RFDLISTPTR1 0x20 +#define IPG_RXDMABURSTTHRESH 0x24 +#define IPG_RXDMAURGENTTHRESH 0x25 +#define IPG_RXDMAPOLLPERIOD 0x26 +#define IPG_RXDMAINTCTRL 0x28 +#define IPG_DEBUGCTRL 0x2C +#define IPG_ASICCTRL 0x30 +#define IPG_FIFOCTRL 0x38 +#define IPG_RXEARLYTHRESH 0x3A +#define IPG_FLOWOFFTHRESH 0x3C +#define IPG_FLOWONTHRESH 0x3E +#define IPG_TXSTARTTHRESH 0x44 +#define IPG_EEPROMDATA 0x48 +#define IPG_EEPROMCTRL 0x4A +#define IPG_EXPROMADDR 0x4C +#define IPG_EXPROMDATA 0x50 +#define IPG_WAKEEVENT 0x51 +#define IPG_COUNTDOWN 0x54 +#define IPG_INTSTATUSACK 0x5A +#define IPG_INTENABLE 0x5C +#define IPG_INTSTATUS 0x5E +#define IPG_TXSTATUS 0x60 +#define IPG_MACCTRL 0x6C +#define IPG_VLANTAG 0x70 +#define IPG_PHYSET 0x75 //JES20040127EEPROM +#define IPG_PHYCTRL 0x76 +#define IPG_STATIONADDRESS0 0x78 +#define IPG_STATIONADDRESS1 0x7A +#define IPG_STATIONADDRESS2 0x7C +#define IPG_MAXFRAMESIZE 0x86 +#define IPG_RECEIVEMODE 0x88 +#define IPG_HASHTABLE0 0x8C +#define IPG_HASHTABLE1 0x90 +#define IPG_RMONSTATISTICSMASK 0x98 +#define IPG_STATISTICSMASK 0x9C +#define IPG_RXJUMBOFRAMES 0xBC +#define IPG_TCPCHECKSUMERRORS 0xC0 +#define IPG_IPCHECKSUMERRORS 0xC2 +#define IPG_UDPCHECKSUMERRORS 0xC4 +#define IPG_TXJUMBOFRAMES 0xF4 + +/* Ethernet MIB statistic register offsets. */ +#define IPG_OCTETRCVOK 0xA8 +#define IPG_MCSTOCTETRCVDOK 0xAC +#define IPG_BCSTOCTETRCVOK 0xB0 +#define IPG_FRAMESRCVDOK 0xB4 +#define IPG_MCSTFRAMESRCVDOK 0xB8 +#define IPG_BCSTFRAMESRCVDOK 0xBE +#define IPG_MACCONTROLFRAMESRCVD 0xC6 +#define IPG_FRAMETOOLONGERRRORS 0xC8 +#define IPG_INRANGELENGTHERRORS 0xCA +#define IPG_FRAMECHECKSEQERRORS 0xCC +#define IPG_FRAMESLOSTRXERRORS 0xCE +#define IPG_OCTETXMTOK 0xD0 +#define IPG_MCSTOCTETXMTOK 0xD4 +#define IPG_BCSTOCTETXMTOK 0xD8 +#define IPG_FRAMESXMTDOK 0xDC +#define IPG_MCSTFRAMESXMTDOK 0xE0 +#define IPG_FRAMESWDEFERREDXMT 0xE4 +#define IPG_LATECOLLISIONS 0xE8 +#define IPG_MULTICOLFRAMES 0xEC +#define IPG_SINGLECOLFRAMES 0xF0 +#define IPG_BCSTFRAMESXMTDOK 0xF6 +#define IPG_CARRIERSENSEERRORS 0xF8 +#define IPG_MACCONTROLFRAMESXMTDOK 0xFA +#define IPG_FRAMESABORTXSCOLLS 0xFC +#define IPG_FRAMESWEXDEFERRAL 0xFE + +/* RMON statistic register offsets. */ +#define IPG_ETHERSTATSCOLLISIONS 0x100 +#define IPG_ETHERSTATSOCTETSTRANSMIT 0x104 +#define IPG_ETHERSTATSPKTSTRANSMIT 0x108 +#define IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT 0x10C +#define IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT 0x110 +#define IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT 0x114 +#define IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT 0x118 +#define IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT 0x11C +#define IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT 0x120 +#define IPG_ETHERSTATSCRCALIGNERRORS 0x124 +#define IPG_ETHERSTATSUNDERSIZEPKTS 0x128 +#define IPG_ETHERSTATSFRAGMENTS 0x12C +#define IPG_ETHERSTATSJABBERS 0x130 +#define IPG_ETHERSTATSOCTETS 0x134 +#define IPG_ETHERSTATSPKTS 0x138 +#define IPG_ETHERSTATSPKTS64OCTESTS 0x13C +#define IPG_ETHERSTATSPKTS65TO127OCTESTS 0x140 +#define IPG_ETHERSTATSPKTS128TO255OCTESTS 0x144 +#define IPG_ETHERSTATSPKTS256TO511OCTESTS 0x148 +#define IPG_ETHERSTATSPKTS512TO1023OCTESTS 0x14C +#define IPG_ETHERSTATSPKTS1024TO1518OCTESTS 0x150 + +/* RMON statistic register equivalents. */ +#define IPG_ETHERSTATSMULTICASTPKTSTRANSMIT 0xE0 +#define IPG_ETHERSTATSBROADCASTPKTSTRANSMIT 0xF6 +#define IPG_ETHERSTATSMULTICASTPKTS 0xB8 +#define IPG_ETHERSTATSBROADCASTPKTS 0xBE +#define IPG_ETHERSTATSOVERSIZEPKTS 0xC8 +#define IPG_ETHERSTATSDROPEVENTS 0xCE + +/* Serial EEPROM offsets */ +#define IPG_EEPROM_CONFIGPARAM 0x00 +#define IPG_EEPROM_ASICCTRL 0x01 +#define IPG_EEPROM_SUBSYSTEMVENDORID 0x02 +#define IPG_EEPROM_SUBSYSTEMID 0x03 +#define IPG_EEPROM_STATIONADDRESS0 0x10 +#define IPG_EEPROM_STATIONADDRESS1 0x11 +#define IPG_EEPROM_STATIONADDRESS2 0x12 + + +/* Register & data structure bit masks */ + +/* PCI register masks. */ + +/* IOBaseAddress */ +#define IPG_PIB_RSVD_MASK 0xFFFFFE01 +#define IPG_PIB_IOBASEADDRESS 0xFFFFFF00 +#define IPG_PIB_IOBASEADDRIND 0x00000001 + +/* MemBaseAddress */ +#define IPG_PMB_RSVD_MASK 0xFFFFFE07 +#define IPG_PMB_MEMBASEADDRIND 0x00000001 +#define IPG_PMB_MEMMAPTYPE 0x00000006 +#define IPG_PMB_MEMMAPTYPE0 0x00000002 +#define IPG_PMB_MEMMAPTYPE1 0x00000004 +#define IPG_PMB_MEMBASEADDRESS 0xFFFFFE00 + +/* ConfigStatus */ +#define IPG_CS_RSVD_MASK 0xFFB0 +#define IPG_CS_CAPABILITIES 0x0010 +#define IPG_CS_66MHZCAPABLE 0x0020 +#define IPG_CS_FASTBACK2BACK 0x0080 +#define IPG_CS_DATAPARITYREPORTED 0x0100 +#define IPG_CS_DEVSELTIMING 0x0600 +#define IPG_CS_SIGNALEDTARGETABORT 0x0800 +#define IPG_CS_RECEIVEDTARGETABORT 0x1000 +#define IPG_CS_RECEIVEDMASTERABORT 0x2000 +#define IPG_CS_SIGNALEDSYSTEMERROR 0x4000 +#define IPG_CS_DETECTEDPARITYERROR 0x8000 + +/* TFD data structure masks. */ + +/* TFDList, TFC */ +#define IPG_TFC_RSVD_MASK 0x0000FFFF9FFFFFFF +#define IPG_TFC_FRAMEID 0x000000000000FFFF +#define IPG_TFC_WORDALIGN 0x0000000000030000 +#define IPG_TFC_WORDALIGNTODWORD 0x0000000000000000 +#define IPG_TFC_WORDALIGNTOWORD 0x0000000000020000 +#define IPG_TFC_WORDALIGNDISABLED 0x0000000000030000 +#define IPG_TFC_TCPCHECKSUMENABLE 0x0000000000040000 +#define IPG_TFC_UDPCHECKSUMENABLE 0x0000000000080000 +#define IPG_TFC_IPCHECKSUMENABLE 0x0000000000100000 +#define IPG_TFC_FCSAPPENDDISABLE 0x0000000000200000 +#define IPG_TFC_TXINDICATE 0x0000000000400000 +#define IPG_TFC_TXDMAINDICATE 0x0000000000800000 +#define IPG_TFC_FRAGCOUNT 0x000000000F000000 +#define IPG_TFC_VLANTAGINSERT 0x0000000010000000 +#define IPG_TFC_TFDDONE 0x0000000080000000 +#define IPG_TFC_VID 0x00000FFF00000000 +#define IPG_TFC_CFI 0x0000100000000000 +#define IPG_TFC_USERPRIORITY 0x0000E00000000000 + +/* TFDList, FragInfo */ +#define IPG_TFI_RSVD_MASK 0xFFFF00FFFFFFFFFF +#define IPG_TFI_FRAGADDR 0x000000FFFFFFFFFF +#define IPG_TFI_FRAGLEN 0xFFFF000000000000LL + +/* RFD data structure masks. */ + +/* RFDList, RFS */ +#define IPG_RFS_RSVD_MASK 0x0000FFFFFFFFFFFF +#define IPG_RFS_RXFRAMELEN 0x000000000000FFFF +#define IPG_RFS_RXFIFOOVERRUN 0x0000000000010000 +#define IPG_RFS_RXRUNTFRAME 0x0000000000020000 +#define IPG_RFS_RXALIGNMENTERROR 0x0000000000040000 +#define IPG_RFS_RXFCSERROR 0x0000000000080000 +#define IPG_RFS_RXOVERSIZEDFRAME 0x0000000000100000 +#define IPG_RFS_RXLENGTHERROR 0x0000000000200000 +#define IPG_RFS_VLANDETECTED 0x0000000000400000 +#define IPG_RFS_TCPDETECTED 0x0000000000800000 +#define IPG_RFS_TCPERROR 0x0000000001000000 +#define IPG_RFS_UDPDETECTED 0x0000000002000000 +#define IPG_RFS_UDPERROR 0x0000000004000000 +#define IPG_RFS_IPDETECTED 0x0000000008000000 +#define IPG_RFS_IPERROR 0x0000000010000000 +#define IPG_RFS_FRAMESTART 0x0000000020000000 +#define IPG_RFS_FRAMEEND 0x0000000040000000 +#define IPG_RFS_RFDDONE 0x0000000080000000 +#define IPG_RFS_TCI 0x0000FFFF00000000 + + +/* RFDList, FragInfo */ +#define IPG_RFI_RSVD_MASK 0xFFFF00FFFFFFFFFF +#define IPG_RFI_FRAGADDR 0x000000FFFFFFFFFF +#define IPG_RFI_FRAGLEN 0xFFFF000000000000LL + +/* I/O Register masks. */ + +/* RMON Statistics Mask */ +#define IPG_RZ_ALL 0x0FFFFFFF + +/* Statistics Mask */ +#define IPG_SM_ALL 0x0FFFFFFF +#define IPG_SM_OCTETRCVOK_FRAMESRCVDOK 0x00000001 +#define IPG_SM_MCSTOCTETRCVDOK_MCSTFRAMESRCVDOK 0x00000002 +#define IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK 0x00000004 +#define IPG_SM_RXJUMBOFRAMES 0x00000008 +#define IPG_SM_TCPCHECKSUMERRORS 0x00000010 +#define IPG_SM_IPCHECKSUMERRORS 0x00000020 +#define IPG_SM_UDPCHECKSUMERRORS 0x00000040 +#define IPG_SM_MACCONTROLFRAMESRCVD 0x00000080 +#define IPG_SM_FRAMESTOOLONGERRORS 0x00000100 +#define IPG_SM_INRANGELENGTHERRORS 0x00000200 +#define IPG_SM_FRAMECHECKSEQERRORS 0x00000400 +#define IPG_SM_FRAMESLOSTRXERRORS 0x00000800 +#define IPG_SM_OCTETXMTOK_FRAMESXMTOK 0x00001000 +#define IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK 0x00002000 +#define IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK 0x00004000 +#define IPG_SM_FRAMESWDEFERREDXMT 0x00008000 +#define IPG_SM_LATECOLLISIONS 0x00010000 +#define IPG_SM_MULTICOLFRAMES 0x00020000 +#define IPG_SM_SINGLECOLFRAMES 0x00040000 +#define IPG_SM_TXJUMBOFRAMES 0x00080000 +#define IPG_SM_CARRIERSENSEERRORS 0x00100000 +#define IPG_SM_MACCONTROLFRAMESXMTD 0x00200000 +#define IPG_SM_FRAMESABORTXSCOLLS 0x00400000 +#define IPG_SM_FRAMESWEXDEFERAL 0x00800000 + + +/* Countdown */ +#define IPG_CD_RSVD_MASK 0x0700FFFF +#define IPG_CD_COUNT 0x0000FFFF +#define IPG_CD_COUNTDOWNSPEED 0x01000000 +#define IPG_CD_COUNTDOWNMODE 0x02000000 +#define IPG_CD_COUNTINTENABLED 0x04000000 + +/* TxDMABurstThresh */ +#define IPG_TB_RSVD_MASK 0xFF + +/* TxDMAUrgentThresh */ +#define IPG_TU_RSVD_MASK 0xFF + +/* TxDMAPollPeriod */ +#define IPG_TP_RSVD_MASK 0xFF + +/* RxDMAUrgentThresh */ +#define IPG_RU_RSVD_MASK 0xFF + +/* RxDMAPollPeriod */ +#define IPG_RP_RSVD_MASK 0xFF + +/* TxStartThresh */ +#define IPG_TT_RSVD_MASK 0x0FFF + +/* RxEarlyThresh */ +#define IPG_RE_RSVD_MASK 0x07FF + +/* ReceiveMode */ +#define IPG_RM_RSVD_MASK 0x3F +#define IPG_RM_RECEIVEUNICAST 0x01 +#define IPG_RM_RECEIVEMULTICAST 0x02 +#define IPG_RM_RECEIVEBROADCAST 0x04 +#define IPG_RM_RECEIVEALLFRAMES 0x08 +#define IPG_RM_RECEIVEMULTICASTHASH 0x10 +#define IPG_RM_RECEIVEIPMULTICAST 0x20 + +/* PhySet JES20040127EEPROM*/ +#define IPG_PS_MEM_LENB9B 0x01 +#define IPG_PS_MEM_LEN9 0x02 +#define IPG_PS_NON_COMPDET 0x04 + +/* PhyCtrl */ +#define IPG_PC_RSVD_MASK 0xFF +#define IPG_PC_MGMTCLK_LO 0x00 +#define IPG_PC_MGMTCLK_HI 0x01 +#define IPG_PC_MGMTCLK 0x01 +#define IPG_PC_MGMTDATA 0x02 +#define IPG_PC_MGMTDIR 0x04 +#define IPG_PC_DUPLEX_POLARITY 0x08 +#define IPG_PC_DUPLEX_STATUS 0x10 +#define IPG_PC_LINK_POLARITY 0x20 +#define IPG_PC_LINK_SPEED 0xC0 +#define IPG_PC_LINK_SPEED_10MBPS 0x40 +#define IPG_PC_LINK_SPEED_100MBPS 0x80 +#define IPG_PC_LINK_SPEED_1000MBPS 0xC0 + +/* DMACtrl */ +#define IPG_DC_RSVD_MASK 0xC07D9818 +#define IPG_DC_RX_DMA_COMPLETE 0x00000008 +#define IPG_DC_RX_DMA_POLL_NOW 0x00000010 +#define IPG_DC_TX_DMA_COMPLETE 0x00000800 +#define IPG_DC_TX_DMA_POLL_NOW 0x00001000 +#define IPG_DC_TX_DMA_IN_PROG 0x00008000 +#define IPG_DC_RX_EARLY_DISABLE 0x00010000 +#define IPG_DC_MWI_DISABLE 0x00040000 +#define IPG_DC_TX_WRITE_BACK_DISABLE 0x00080000 +#define IPG_DC_TX_BURST_LIMIT 0x00700000 +#define IPG_DC_TARGET_ABORT 0x40000000 +#define IPG_DC_MASTER_ABORT 0x80000000 + +/* ASICCtrl */ +#define IPG_AC_RSVD_MASK 0x07FFEFF2 +#define IPG_AC_EXP_ROM_SIZE 0x00000002 +#define IPG_AC_PHY_SPEED10 0x00000010 +#define IPG_AC_PHY_SPEED100 0x00000020 +#define IPG_AC_PHY_SPEED1000 0x00000040 +#define IPG_AC_PHY_MEDIA 0x00000080 +#define IPG_AC_FORCED_CFG 0x00000700 +#define IPG_AC_D3RESETDISABLE 0x00000800 +#define IPG_AC_SPEED_UP_MODE 0x00002000 +#define IPG_AC_LED_MODE 0x00004000 +#define IPG_AC_RST_OUT_POLARITY 0x00008000 +#define IPG_AC_GLOBAL_RESET 0x00010000 +#define IPG_AC_RX_RESET 0x00020000 +#define IPG_AC_TX_RESET 0x00040000 +#define IPG_AC_DMA 0x00080000 +#define IPG_AC_FIFO 0x00100000 +#define IPG_AC_NETWORK 0x00200000 +#define IPG_AC_HOST 0x00400000 +#define IPG_AC_AUTO_INIT 0x00800000 +#define IPG_AC_RST_OUT 0x01000000 +#define IPG_AC_INT_REQUEST 0x02000000 +#define IPG_AC_RESET_BUSY 0x04000000 +#define IPG_AC_LED_SPEED 0x08000000 //JES20040127EEPROM +#define IPG_AC_LED_MODE_BIT_1 0x20000000 //JES20040127EEPROM + +/* EepromCtrl */ +#define IPG_EC_RSVD_MASK 0x83FF +#define IPG_EC_EEPROM_ADDR 0x00FF +#define IPG_EC_EEPROM_OPCODE 0x0300 +#define IPG_EC_EEPROM_SUBCOMMAD 0x0000 +#define IPG_EC_EEPROM_WRITEOPCODE 0x0100 +#define IPG_EC_EEPROM_READOPCODE 0x0200 +#define IPG_EC_EEPROM_ERASEOPCODE 0x0300 +#define IPG_EC_EEPROM_BUSY 0x8000 + +/* FIFOCtrl */ +#define IPG_FC_RSVD_MASK 0xC001 +#define IPG_FC_RAM_TEST_MODE 0x0001 +#define IPG_FC_TRANSMITTING 0x4000 +#define IPG_FC_RECEIVING 0x8000 + +/* TxStatus */ +#define IPG_TS_RSVD_MASK 0xFFFF00DD +#define IPG_TS_TX_ERROR 0x00000001 +#define IPG_TS_LATE_COLLISION 0x00000004 +#define IPG_TS_TX_MAX_COLL 0x00000008 +#define IPG_TS_TX_UNDERRUN 0x00000010 +#define IPG_TS_TX_IND_REQD 0x00000040 +#define IPG_TS_TX_COMPLETE 0x00000080 +#define IPG_TS_TX_FRAMEID 0xFFFF0000 + +/* WakeEvent */ +#define IPG_WE_WAKE_PKT_ENABLE 0x01 +#define IPG_WE_MAGIC_PKT_ENABLE 0x02 +#define IPG_WE_LINK_EVT_ENABLE 0x04 +#define IPG_WE_WAKE_POLARITY 0x08 +#define IPG_WE_WAKE_PKT_EVT 0x10 +#define IPG_WE_MAGIC_PKT_EVT 0x20 +#define IPG_WE_LINK_EVT 0x40 +#define IPG_WE_WOL_ENABLE 0x80 + +/* IntEnable */ +#define IPG_IE_RSVD_MASK 0x1FFE +#define IPG_IE_HOST_ERROR 0x0002 +#define IPG_IE_TX_COMPLETE 0x0004 +#define IPG_IE_MAC_CTRL_FRAME 0x0008 +#define IPG_IE_RX_COMPLETE 0x0010 +#define IPG_IE_RX_EARLY 0x0020 +#define IPG_IE_INT_REQUESTED 0x0040 +#define IPG_IE_UPDATE_STATS 0x0080 +#define IPG_IE_LINK_EVENT 0x0100 +#define IPG_IE_TX_DMA_COMPLETE 0x0200 +#define IPG_IE_RX_DMA_COMPLETE 0x0400 +#define IPG_IE_RFD_LIST_END 0x0800 +#define IPG_IE_RX_DMA_PRIORITY 0x1000 + +/* IntStatus */ +#define IPG_IS_RSVD_MASK 0x1FFF +#define IPG_IS_INTERRUPT_STATUS 0x0001 +#define IPG_IS_HOST_ERROR 0x0002 +#define IPG_IS_TX_COMPLETE 0x0004 +#define IPG_IS_MAC_CTRL_FRAME 0x0008 +#define IPG_IS_RX_COMPLETE 0x0010 +#define IPG_IS_RX_EARLY 0x0020 +#define IPG_IS_INT_REQUESTED 0x0040 +#define IPG_IS_UPDATE_STATS 0x0080 +#define IPG_IS_LINK_EVENT 0x0100 +#define IPG_IS_TX_DMA_COMPLETE 0x0200 +#define IPG_IS_RX_DMA_COMPLETE 0x0400 +#define IPG_IS_RFD_LIST_END 0x0800 +#define IPG_IS_RX_DMA_PRIORITY 0x1000 + +/* MACCtrl */ +#define IPG_MC_RSVD_MASK 0x7FE33FA3 +#define IPG_MC_IFS_SELECT 0x00000003 +#define IPG_MC_IFS_4352BIT 0x00000003 +#define IPG_MC_IFS_1792BIT 0x00000002 +#define IPG_MC_IFS_1024BIT 0x00000001 +#define IPG_MC_IFS_96BIT 0x00000000 +#define IPG_MC_DUPLEX_SELECT 0x00000020 +#define IPG_MC_DUPLEX_SELECT_FD 0x00000020 +#define IPG_MC_DUPLEX_SELECT_HD 0x00000000 +#define IPG_MC_TX_FLOW_CONTROL_ENABLE 0x00000080 +#define IPG_MC_RX_FLOW_CONTROL_ENABLE 0x00000100 +#define IPG_MC_RCV_FCS 0x00000200 +#define IPG_MC_FIFO_LOOPBACK 0x00000400 +#define IPG_MC_MAC_LOOPBACK 0x00000800 +#define IPG_MC_AUTO_VLAN_TAGGING 0x00001000 +#define IPG_MC_AUTO_VLAN_UNTAGGING 0x00002000 +#define IPG_MC_COLLISION_DETECT 0x00010000 +#define IPG_MC_CARRIER_SENSE 0x00020000 +#define IPG_MC_STATISTICS_ENABLE 0x00200000 +#define IPG_MC_STATISTICS_DISABLE 0x00400000 +#define IPG_MC_STATISTICS_ENABLED 0x00800000 +#define IPG_MC_TX_ENABLE 0x01000000 +#define IPG_MC_TX_DISABLE 0x02000000 +#define IPG_MC_TX_ENABLED 0x04000000 +#define IPG_MC_RX_ENABLE 0x08000000 +#define IPG_MC_RX_DISABLE 0x10000000 +#define IPG_MC_RX_ENABLED 0x20000000 +#define IPG_MC_PAUSED 0x40000000 + +/* RxDMAIntCtrl */ +#define IPG_RI_RSVD_MASK 0xFFFF1CFF +#define IPG_RI_RXFRAME_COUNT 0x000000FF +#define IPG_RI_PRIORITY_THRESH 0x00001C00 +#define IPG_RI_RXDMAWAIT_TIME 0xFFFF0000 + +/* end ipg_constants.h */ diff --git a/drivers/net/ip1000a/ipg_macros.h b/drivers/net/ip1000a/ipg_macros.h new file mode 100644 index 0000000..0d0d31a --- /dev/null +++ b/drivers/net/ip1000a/ipg_macros.h @@ -0,0 +1,462 @@ +/* + * + * ipg_macros.h + * + * Include file with macros for Gigabit Ethernet + * device driver for Network Interface Cards (NICs) utilizing the + * Tamarack Microelectronics Inc. IPG Gigabit or Triple Speed + * Ethernet Media Access Controller. + * + * Craig Rich + * Sundance Technology, Inc. + * 1485 Saratoga Avenue + * Suite 200 + * San Jose, CA 95129 + * 408 873 4117 + * www.sundanceti.com + * craig_rich@sundanceti.com + * + * Rev Date Description + * -------------------------------------------------------------- + * 0.1 3/30/01 New file created from original ipg.h + */ + +/* + * Miscellaneous macros. + */ + +/* Marco for printing debug statements. +# define IPG_DDEBUG_MSG(args...) printk(KERN_DEBUG "IPG: " ## args) */ +#ifdef IPG_DEBUG +# define IPG_DEBUG_MSG(args...) +# define IPG_DDEBUG_MSG(args...) printk(KERN_DEBUG "IPG: " args) +# define IPG_DUMPRFDLIST(args) ipg_dump_rfdlist(args) +# define IPG_DUMPTFDLIST(args) ipg_dump_tfdlist(args) +#else +# define IPG_DEBUG_MSG(args...) +# define IPG_DDEBUG_MSG(args...) +# define IPG_DUMPRFDLIST(args) +# define IPG_DUMPTFDLIST(args) +#endif + +/* + * End miscellaneous macros. + */ + +/* + * Register access macros. + */ + +#ifdef USE_IO_OPS + +/* Use I/O access for IPG registers. */ + +#define RD8 inb +#define RD16 inw +#define RD32 inl +#define WR8 outb +#define WR16 outw +#define WR32 outl + +#else + +/* Use memory access for IPG registers. */ + +#define RD8 readb +#define RD16 readw +#define RD32 readl +#define WR8 writeb +#define WR16 writew +#define WR32 writel + +#endif + +#define IPG_READ_BYTEREG(regaddr) RD8(regaddr) + +#define IPG_READ_WORDREG(regaddr) RD16(regaddr) + +#define IPG_READ_LONGREG(regaddr) RD32(regaddr) + +#define IPG_WRITE_BYTEREG(regaddr, writevalue) WR8(writevalue, regaddr) + +#define IPG_WRITE_WORDREG(regaddr, writevalue) WR16(writevalue, regaddr) + +#define IPG_WRITE_LONGREG(regaddr, writevalue) WR32(writevalue, regaddr) + +#define IPG_READ_ASICCTRL(baseaddr) RD32(baseaddr + IPG_ASICCTRL) + +//Jesse20040128EEPROM_VALUE +//#define IPG_WRITE_ASICCTRL(baseaddr, writevalue) WR32(IPG_AC_RSVD_MASK & (writevalue), baseaddr + IPG_ASICCTRL) +#define IPG_WRITE_ASICCTRL(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ASICCTRL) + +#define IPG_READ_EEPROMCTRL(baseaddr) RD16(baseaddr + IPG_EEPROMCTRL) + +#define IPG_WRITE_EEPROMCTRL(baseaddr, writevalue) WR16(IPG_EC_RSVD_MASK & (writevalue), baseaddr + IPG_EEPROMCTRL) + +#define IPG_READ_EEPROMDATA(baseaddr) RD16(baseaddr + IPG_EEPROMDATA) + +#define IPG_WRITE_EEPROMDATA(baseaddr, writevalue) WR16(writevalue, (baseaddr + IPG_EEPROMDATA) + +#define IPG_READ_PHYSET(baseaddr) RD8(baseaddr + IPG_PHYSET)//Jesse20040128EEPROM_VALUE + +#define IPG_WRITE_PHYSET(baseaddr, writevalue) WR8(writevalue, baseaddr + IPG_PHYSET)//Jesse20040128EEPROM_VALUE + +#define IPG_READ_PHYCTRL(baseaddr) RD8(baseaddr + IPG_PHYCTRL) + +#define IPG_WRITE_PHYCTRL(baseaddr, writevalue) WR8(IPG_PC_RSVD_MASK & (writevalue), baseaddr + IPG_PHYCTRL) + +#define IPG_READ_RECEIVEMODE(baseaddr) RD8(baseaddr + IPG_RECEIVEMODE) + +#define IPG_WRITE_RECEIVEMODE(baseaddr, writevalue) WR8(IPG_RM_RSVD_MASK & (writevalue), baseaddr + IPG_RECEIVEMODE) + +#define IPG_READ_MAXFRAMESIZE(baseaddr) RD16(baseaddr + IPG_MAXFRAMESIZE) + +#define IPG_WRITE_MAXFRAMESIZE(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_MAXFRAMESIZE) + +#define IPG_READ_MACCTRL(baseaddr) RD32(baseaddr + IPG_MACCTRL) + +#define IPG_WRITE_MACCTRL(baseaddr, writevalue) WR32(IPG_MC_RSVD_MASK & (writevalue), baseaddr + IPG_MACCTRL) + +#define IPG_READ_INTSTATUSACK(baseaddr) RD16(baseaddr + IPG_INTSTATUSACK) + +#define IPG_READ_INTSTATUS(baseaddr) RD16(baseaddr + IPG_INTSTATUS) + +#define IPG_WRITE_INTSTATUS(baseaddr, writevalue) WR16(IPG_IS_RSVD_MASK & (writevalue), baseaddr + IPG_INTSTATUS) + +#define IPG_READ_INTENABLE(baseaddr) RD16(baseaddr + IPG_INTENABLE) + +#define IPG_WRITE_INTENABLE(baseaddr, writevalue) WR16(IPG_IE_RSVD_MASK & (writevalue), baseaddr + IPG_INTENABLE) + +#define IPG_READ_WAKEEVENT(baseaddr) RD8(baseaddr + IPG_WAKEEVENT) + +#define IPG_WRITE_WAKEEVENT(baseaddr, writevalue) WR8(writevalue, baseaddr + IPG_WAKEEVENT) + +#define IPG_READ_RXEARLYTHRESH(baseaddr) RD16(baseaddr + IPG_RXEARLYTHRESH) + +#define IPG_WRITE_RXEARLYTHRESH(baseaddr, writevalue) WR16(IPG_RE_RSVD_MASK & (writevalue), baseaddr + IPG_RXEARLYTHRESH) + +#define IPG_READ_TXSTARTTHRESH(baseaddr) RD32(baseaddr + IPG_TXSTARTTHRESH) + +#define IPG_WRITE_TXSTARTTHRESH(baseaddr, writevalue) WR32(IPG_TT_RSVD_MASK & (writevalue), baseaddr + IPG_TXSTARTTHRESH) + +#define IPG_READ_FIFOCTRL(baseaddr) RD16(baseaddr + IPG_FIFOCTRL) + +#define IPG_WRITE_FIFOCTRL(baseaddr, writevalue) WR16(IPG_FC_RSVD_MASK & (writevalue), baseaddr + IPG_FIFOCTRL) + +#define IPG_READ_RXDMAPOLLPERIOD(baseaddr) RD8(baseaddr + IPG_RXDMAPOLLPERIOD) + +#define IPG_WRITE_RXDMAPOLLPERIOD(baseaddr, writevalue) WR8(IPG_RP_RSVD_MASK & (writevalue), baseaddr + IPG_RXDMAPOLLPERIOD) + +#define IPG_READ_RXDMAURGENTTHRESH(baseaddr) RD8(baseaddr + IPG_RXDMAURGENTTHRESH) + +#define IPG_WRITE_RXDMAURGENTTHRESH(baseaddr, writevalue) WR8(IPG_RU_RSVD_MASK & (writevalue), baseaddr + IPG_RXDMAURGENTTHRESH) + +#define IPG_READ_RXDMABURSTTHRESH(baseaddr) RD8(baseaddr + IPG_RXDMABURSTTHRESH) + +#define IPG_WRITE_RXDMABURSTTHRESH(baseaddr, writevalue) WR8(writevalue, baseaddr + IPG_RXDMABURSTTHRESH) + +#define IPG_READ_RFDLISTPTR0(baseaddr) RD32(baseaddr + IPG_RFDLISTPTR0) + +#define IPG_WRITE_RFDLISTPTR0(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_RFDLISTPTR0) + +#define IPG_READ_RFDLISTPTR1(baseaddr) RD32(baseaddr + IPG_RFDLISTPTR1) + +#define IPG_WRITE_RFDLISTPTR1(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_RFDLISTPTR1) + +#define IPG_READ_TXDMAPOLLPERIOD(baseaddr) RD8(baseaddr + IPG_TXDMAPOLLPERIOD) + +#define IPG_WRITE_TXDMAPOLLPERIOD(baseaddr, writevalue) WR8(IPG_TP_RSVD_MASK & (writevalue), baseaddr + IPG_TXDMAPOLLPERIOD) + +#define IPG_READ_TXDMAURGENTTHRESH(baseaddr) RD8(baseaddr + IPG_TXDMAURGENTTHRESH) + +#define IPG_WRITE_TXDMAURGENTTHRESH(baseaddr, writevalue) WR8(IPG_TU_RSVD_MASK & (writevalue), baseaddr + IPG_TXDMAURGENTTHRESH) + +#define IPG_READ_TXDMABURSTTHRESH(baseaddr) RD8(baseaddr + IPG_TXDMABURSTTHRESH) + +#define IPG_WRITE_TXDMABURSTTHRESH(baseaddr, writevalue) WR8(IPG_TB_RSVD_MASK & (writevalue), baseaddr + IPG_TXDMABURSTTHRESH) + +#define IPG_READ_TFDLISTPTR0(baseaddr) RD32(baseaddr + IPG_TFDLISTPTR0) + +#define IPG_WRITE_TFDLISTPTR0(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_TFDLISTPTR0) + +#define IPG_READ_TFDLISTPTR1(baseaddr) RD32(baseaddr + IPG_TFDLISTPTR1) + +#define IPG_WRITE_TFDLISTPTR1(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_TFDLISTPTR1) + +#define IPG_READ_DMACTRL(baseaddr) RD32(baseaddr + IPG_DMACTRL) + +#define IPG_WRITE_DMACTRL(baseaddr, writevalue) WR32(IPG_DC_RSVD_MASK & (writevalue), baseaddr + IPG_DMACTRL) + +#define IPG_READ_TXSTATUS(baseaddr) RD32(baseaddr + IPG_TXSTATUS) + +#define IPG_WRITE_TXSTATUS(baseaddr, writevalue) WR32(IPG_TS_RSVD_MASK & (writevalue), baseaddr + IPG_TXSTATUS) + +#define IPG_READ_STATIONADDRESS0(baseaddr) RD16(baseaddr + IPG_STATIONADDRESS0) + +#define IPG_READ_STATIONADDRESS1(baseaddr) RD16(baseaddr + IPG_STATIONADDRESS1) + +#define IPG_READ_STATIONADDRESS2(baseaddr) RD16(baseaddr + IPG_STATIONADDRESS2) + +#define IPG_WRITE_STATIONADDRESS0(baseaddr,writevalue) WR16(writevalue,baseaddr + IPG_STATIONADDRESS0)//JES20040127EEPROM + +#define IPG_WRITE_STATIONADDRESS1(baseaddr,writevalue) WR16(writevalue,baseaddr + IPG_STATIONADDRESS1)//JES20040127EEPROM + +#define IPG_WRITE_STATIONADDRESS2(baseaddr,writevalue) WR16(writevalue,baseaddr + IPG_STATIONADDRESS2)//JES20040127EEPROM + +#define IPG_READ_COUNTDOWN(baseaddr) RD32(baseaddr + IPG_COUNTDOWN) + +#define IPG_WRITE_COUNTDOWN(baseaddr, writevalue) WR32(IPG_CD_RSVD_MASK & (writevalue), baseaddr + IPG_COUNTDOWN) + +#define IPG_READ_RXDMASTATUS(baseaddr) RD16(baseaddr + IPG_RXDMASTATUS) + +#define IPG_WRITE_HASHTABLE0(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_HASHTABLE0) + +#define IPG_WRITE_HASHTABLE1(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_HASHTABLE1) + +#define IPG_READ_STATISTICSMASK(baseaddr) RD32(baseaddr + IPG_STATISTICSMASK) + +#define IPG_WRITE_STATISTICSMASK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_STATISTICSMASK) + +#define IPG_READ_RMONSTATISTICSMASK(baseaddr) RD32(baseaddr + IPG_RMONSTATISTICSMASK) + +#define IPG_WRITE_RMONSTATISTICSMASK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_RMONSTATISTICSMASK) + +#define IPG_READ_VLANTAG(baseaddr) RD32(baseaddr + IPG_VLANTAG) + +#define IPG_WRITE_VLANTAG(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_VLANTAG) + +#define IPG_READ_FLOWONTHRESH(baseaddr) RD16(baseaddr + IPG_FLOWONTHRESH) + +#define IPG_WRITE_FLOWONTHRESH(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FLOWONTHRESH) + +#define IPG_READ_FLOWOFFTHRESH(baseaddr) RD16(baseaddr + IPG_FLOWOFFTHRESH) + +#define IPG_WRITE_FLOWOFFTHRESH(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FLOWOFFTHRESH) + +#define IPG_READ_DEBUGCTRL(baseaddr) RD16(baseaddr + IPG_DEBUGCTRL) + +#define IPG_WRITE_DEBUGCTRL(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_DEBUGCTRL) + +#define IPG_READ_RXDMAINTCTRL(baseaddr) RD32(baseaddr + IPG_RXDMAINTCTRL) + +#define IPG_WRITE_RXDMAINTCTRL(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_RXDMAINTCTRL) + +#define IPG_READ_TXJUMBOFRAMES(baseaddr) RD16(baseaddr + IPG_TXJUMBOFRAMES) + +#define IPG_WRITE_TXJUMBOFRAMES(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_TXJUMBOFRAMES) + +#define IPG_READ_UDPCHECKSUMERRORS(baseaddr) RD16(baseaddr + IPG_UDPCHECKSUMERRORS) + +#define IPG_WRITE_UDPCHECKSUMERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_UDPCHECKSUMERRORS) + +#define IPG_READ_IPCHECKSUMERRORS(baseaddr) RD16(baseaddr + IPG_IPCHECKSUMERRORS) + +#define IPG_WRITE_IPCHECKSUMERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_IPCHECKSUMERRORS) + +#define IPG_READ_TCPCHECKSUMERRORS(baseaddr) RD16(baseaddr + IPG_TCPCHECKSUMERRORS) + +#define IPG_WRITE_TCPCHECKSUMERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_TCPCHECKSUMERRORS) + +#define IPG_READ_RXJUMBOFRAMES(baseaddr) RD16(baseaddr + IPG_RXJUMBOFRAMES) + +#define IPG_WRITE_RXJUMBOFRAMES(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_RXJUMBOFRAMES) + + + +/* Statistic register read/write macros. */ + +#define IPG_READ_OCTETRCVOK(baseaddr) RD32(baseaddr + IPG_OCTETRCVOK) + +#define IPG_WRITE_OCTETRCVOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_OCTETRCVOK) + +#define IPG_READ_MCSTOCTETRCVDOK(baseaddr) RD32(baseaddr + IPG_MCSTOCTETRCVDOK) + +#define IPG_WRITE_MCSTOCTETRCVDOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_MCSTOCTETRCVDOK) + +#define IPG_READ_BCSTOCTETRCVOK(baseaddr) RD32(baseaddr + IPG_BCSTOCTETRCVOK) + +#define IPG_WRITE_BCSTOCTETRCVOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_BCSTOCTETRCVOK) + +#define IPG_READ_FRAMESRCVDOK(baseaddr) RD32(baseaddr + IPG_FRAMESRCVDOK) + +#define IPG_WRITE_FRAMESRCVDOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_FRAMESRCVDOK) + +#define IPG_READ_MCSTFRAMESRCVDOK(baseaddr) RD32(baseaddr + IPG_MCSTFRAMESRCVDOK) + +#define IPG_WRITE_MCSTFRAMESRCVDOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_MCSTFRAMESRCVDOK) + +#define IPG_READ_BCSTFRAMESRCVDOK(baseaddr) RD16(baseaddr + IPG_BCSTFRAMESRCVDOK) + +#define IPG_WRITE_BCSTFRAMESRCVDOK(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_BCSTFRAMESRCVDOK) + +#define IPG_READ_MACCONTROLFRAMESRCVD(baseaddr) RD16(baseaddr + IPG_MACCONTROLFRAMESRCVD) + +#define IPG_WRITE_MACCONTROLFRAMESRCVD(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_MACCONTROLFRAMESRCVD) + +#define IPG_READ_FRAMETOOLONGERRRORS(baseaddr) RD16(baseaddr + IPG_FRAMETOOLONGERRRORS) + +#define IPG_WRITE_FRAMETOOLONGERRRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMETOOLONGERRRORS) + +#define IPG_READ_INRANGELENGTHERRORS(baseaddr) RD16(baseaddr + IPG_INRANGELENGTHERRORS) + +#define IPG_WRITE_INRANGELENGTHERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_INRANGELENGTHERRORS) + +#define IPG_READ_FRAMECHECKSEQERRORS(baseaddr) RD16(baseaddr + IPG_FRAMECHECKSEQERRORS) + +#define IPG_WRITE_FRAMECHECKSEQERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMECHECKSEQERRORS) + +#define IPG_READ_FRAMESLOSTRXERRORS(baseaddr) RD16(baseaddr + IPG_FRAMESLOSTRXERRORS) + +#define IPG_WRITE_FRAMESLOSTRXERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMESLOSTRXERRORS) + +#define IPG_READ_FRAMESLOSTRXERRORS(baseaddr) RD16(baseaddr + IPG_FRAMESLOSTRXERRORS) + +#define IPG_WRITE_FRAMESLOSTRXERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMESLOSTRXERRORS) + +#define IPG_READ_OCTETXMTOK(baseaddr) RD32(baseaddr + IPG_OCTETXMTOK) + +#define IPG_WRITE_OCTETXMTOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_OCTETXMTOK) + +#define IPG_READ_MCSTOCTETXMTOK(baseaddr) RD32(baseaddr + IPG_MCSTOCTETXMTOK) + +#define IPG_WRITE_MCSTOCTETXMTOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_MCSTOCTETXMTOK) + +#define IPG_READ_BCSTOCTETXMTOK(baseaddr) RD32(baseaddr + IPG_BCSTOCTETXMTOK) + +#define IPG_WRITE_BCSTOCTETXMTOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_BCSTOCTETXMTOK) + +#define IPG_READ_FRAMESXMTDOK(baseaddr) RD32(baseaddr + IPG_FRAMESXMTDOK) + +#define IPG_WRITE_FRAMESXMTDOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_FRAMESXMTDOK) + +#define IPG_READ_MCSTFRAMESXMTDOK(baseaddr) RD32(baseaddr + IPG_MCSTFRAMESXMTDOK) + +#define IPG_WRITE_MCSTFRAMESXMTDOK(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_MCSTFRAMESXMTDOK) + +#define IPG_READ_FRAMESWDEFERREDXMT(baseaddr) RD32(baseaddr + IPG_FRAMESWDEFERREDXMT) + +#define IPG_WRITE_FRAMESWDEFERREDXMT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_FRAMESWDEFERREDXMT) + +#define IPG_READ_LATECOLLISIONS(baseaddr) RD32(baseaddr + IPG_LATECOLLISIONS) + +#define IPG_WRITE_LATECOLLISIONS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_LATECOLLISIONS) + +#define IPG_READ_MULTICOLFRAMES(baseaddr) RD32(baseaddr + IPG_MULTICOLFRAMES) + +#define IPG_WRITE_MULTICOLFRAMES(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_MULTICOLFRAMES) + +#define IPG_READ_SINGLECOLFRAMES(baseaddr) RD32(baseaddr + IPG_SINGLECOLFRAMES) + +#define IPG_WRITE_SINGLECOLFRAMES(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_SINGLECOLFRAMES) + +#define IPG_READ_BCSTFRAMESXMTDOK(baseaddr) RD16(baseaddr + IPG_BCSTFRAMESXMTDOK) + +#define IPG_WRITE_BCSTFRAMESXMTDOK(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_BCSTFRAMESXMTDOK) + +#define IPG_READ_CARRIERSENSEERRORS(baseaddr) RD16(baseaddr + IPG_CARRIERSENSEERRORS) + +#define IPG_WRITE_CARRIERSENSEERRORS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_CARRIERSENSEERRORS) + +#define IPG_READ_MACCONTROLFRAMESXMTDOK(baseaddr) RD16(baseaddr + IPG_MACCONTROLFRAMESXMTDOK) + +#define IPG_WRITE_MACCONTROLFRAMESXMTDOK(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_MACCONTROLFRAMESXMTDOK) + +#define IPG_READ_FRAMESABORTXSCOLLS(baseaddr) RD16(baseaddr + IPG_FRAMESABORTXSCOLLS) + +#define IPG_WRITE_FRAMESABORTXSCOLLS(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMESABORTXSCOLLS) + +#define IPG_READ_FRAMESWEXDEFERRAL(baseaddr) RD16(baseaddr + IPG_FRAMESWEXDEFERRAL) + +#define IPG_WRITE_FRAMESWEXDEFERRAL(baseaddr, writevalue) WR16(writevalue, baseaddr + IPG_FRAMESWEXDEFERRAL) + +/* RMON statistic register read/write macros. */ + +#define IPG_READ_ETHERSTATSCOLLISIONS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSCOLLISIONS) + +#define IPG_WRITE_ETHERSTATSCOLLISIONS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSCOLLISIONS) + +#define IPG_READ_ETHERSTATSOCTETSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSOCTETSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSOCTETSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSOCTETSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS64OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS64OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT) + +#define IPG_WRITE_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT) + +#define IPG_READ_ETHERSTATSCRCALIGNERRORS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSCRCALIGNERRORS) + +#define IPG_WRITE_ETHERSTATSCRCALIGNERRORS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSCRCALIGNERRORS) + +#define IPG_READ_ETHERSTATSUNDERSIZEPKTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSUNDERSIZEPKTS) + +#define IPG_WRITE_ETHERSTATSUNDERSIZEPKTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSUNDERSIZEPKTS) + +#define IPG_READ_ETHERSTATSFRAGMENTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSFRAGMENTS) + +#define IPG_WRITE_ETHERSTATSFRAGMENTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSFRAGMENTS) + +#define IPG_READ_ETHERSTATSJABBERS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSJABBERS) + +#define IPG_WRITE_ETHERSTATSJABBERS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSJABBERS) + +#define IPG_READ_ETHERSTATSOCTETS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSOCTETS) + +#define IPG_WRITE_ETHERSTATSOCTETS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSOCTETS) + +#define IPG_READ_ETHERSTATSPKTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS) + +#define IPG_WRITE_ETHERSTATSPKTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS) + +#define IPG_READ_ETHERSTATSPKTS64OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS64OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS64OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS64OCTESTS) + +#define IPG_READ_ETHERSTATSPKTS65TO127OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS65TO127OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS65TO127OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS65TO127OCTESTS) + +#define IPG_READ_ETHERSTATSPKTS128TO255OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS128TO255OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS128TO255OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS128TO255OCTESTS) + +#define IPG_READ_ETHERSTATSPKTS256TO511OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS256TO511OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS256TO511OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS256TO511OCTESTS) + +#define IPG_READ_ETHERSTATSPKTS512TO1023OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS512TO1023OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS512TO1023OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS512TO1023OCTESTS) + +#define IPG_READ_ETHERSTATSPKTS1024TO1518OCTESTS(baseaddr) RD32(baseaddr + IPG_ETHERSTATSPKTS1024TO1518OCTESTS) + +#define IPG_WRITE_ETHERSTATSPKTS1024TO1518OCTESTS(baseaddr, writevalue) WR32(writevalue, baseaddr + IPG_ETHERSTATSPKTS1024TO1518OCTESTS) + +/* + * End register access macros. + */ + +/* end ipg_macros.h */ diff --git a/drivers/net/ip1000a/ipg_main.c b/drivers/net/ip1000a/ipg_main.c new file mode 100644 index 0000000..11223c7 --- /dev/null +++ b/drivers/net/ip1000a/ipg_main.c @@ -0,0 +1,4289 @@ +/*PCI_DEVICE_ID_IP1000 + * + * ipg.c + * + * IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver v2.01 + * by IC Plus Corp. 2003 + * + * Craig Rich + * Sundance Technology, Inc. + * 1485 Saratoga Avenue + * Suite 200 + * San Jose, CA 95129 + * 408 873 4117 + * www.sundanceti.com + * craig_rich@sundanceti.com + * + * Rev Date Description + * -------------------------------------------------------------- + * 0.1 11/8/99 Initial revision work begins. + * + * 0.2 11/12/99 Basic operation achieved, continuing work. + * + * 0.3 11/19/99 MAC Loop Back for sync problem testing. + * + * 0.4 12/22/99 ioctl for diagnotic program 'hunter' support. + * + * 0.5 4/13/00 Updates to + * + * 0.6 6/14/00 Slight correction to handling TFDDONE, and + * preservation of PHYCTRL polarity bits. + * + * 0.7 7/27/00 Modifications to accomodate triple speed + * autonegotiation. Also change to ioctl routine + * to handle unknown PHY address. + * + * 0.8 8/11/00 Added change_mtu function. + * + * 0.9 8/15/00 Corrected autonegotiation resolution. + * + * 0.10 8/30/00 Changed constants to use IPG in place + * of RIO. Also, removed most of debug + * code in preparation for production release. + * + * 0.11 8/31/00 Utilize 64 bit data types where appropriate. + * + * 0.12 9/1/00 Move some constants to include file and utilize + * RxDMAInt register. + * + * 0.13 10/31/00 Several minor modifications to improve stability. + * + * 0.14 11/28/00 Added call to nic_tx_free if TFD not available. + * + * 0.15 12/5/00 Corrected problem with receive errors, always set + * receive buffer address to NULL. Release RX buffers + * on errors. + * + * 0.16 12/20/00 Corrected autoneg resolution issue, must detect + * speed via PHYCTRL register. Also, perform only 1 + * loop in the nic_txcleanup routine. + * + * 0.17 2/7/01 Changed all references of ST2021 to IPG. + * When next TFD not available, return -ENOMEM instead + * of 0. Removed references to RUBICON. + * + * 0.18 2/14/01 Corrected problem when unexpected jumbo frames are + * received (now dropped properly.) Changed + * "DROP_ON_ERRORS" breaking out Ethernet errors and + * TCP/IP errors serparately. Corrected Gigabit + * copper PAUSE autonegotiation. + * + * 0.19 2/22/01 Changed interrupt handling of RFD_LIST_END, + * INT_REQUESTED, and RX_DMA_COMPLETE. Masked off + * RMON statistics and unused MIB statistics. + * Make sure *all* statistics are accounted for + * (either masked or read in get_stats) to avoid + * perpetual UpdateStats interrupt from causing + * driver to crash. + * + * 0.20 3/2/01 Corrected error in nic_stop. Need to set + * TxBuff[] = NULL after freeing TxBuff and + * RxBuff[] = NULL after freeing RxBuff. + * + * 0.21 3/5/01 Correct 10/100Mbit PAUSE autonegotiation. + * + * 0.22 3/16/01 Used TxDMAIndicate for 100/1000Mbps modes. Add + * "TFD unavailable" and "RFD list end" counters + * to assist with performance measurement. Added + * check for maxtfdcnt != 0 to while loop within + * txcleanup. + * + * 0.23 3/22/01 Set the CurrentTxFrameID to 1 upon detecting + * a TxDMAComplete to reduce the number of TxDMAComplete. + * Also, indicate IP/TCP/UDP checksum is unneseccary + * if IPG indicates checksum validates. + * + * 0.24 3/23/01 Changed the txfree routine, eliminating the margin + * between the last freed TFD and the current TFD. + * + * 0.25 4/3/01 Corrected errors in config_autoneg to deal with + * fiber flag properly. + * + * 0.26 5/1/01 Port for operation with Linux 2.2 or 2.4 kernel. + * + * 0.27 5/22/01 Cleaned up some extraneous comments. + * + * 0.28 6/20/01 Added auto IP, TCP, and UDP checksum addition + * on transmit based on compilation option. + * + * 0.29 7/26/01 Comment out #include from ipg.h + * for compatibility with RedHat 7.1. Unkown reason. + * + * 0.30 8/10/01 Added debug message to each function, print function + * name when entered. Added DEBUGCTRL register bit 5 for + * Rx DMA Poll Now bug work around. Added ifdef IPG_DEBUG + * flags to IPG_TFDlistunabvail and IPG_RFDlistend + * counters. Removed clearing of sp->stat struct from + * nic_open and added check in get_stats to make sure + * NIC is initialized before reading statistic registers. + * Corrected erroneous MACCTRL setting for Fiber based + * 10/100 boards. Corrected storage of phyctrlpolarity + * variable. + * + * 0.31 8/13/01 Incorporate STI or TMI fiber based NIC detection. + * Corrected problem with _pciremove_linux2_4 routine. + * Corrected setting of IP/TCP/UDP checksumming on receive + * and transmit. + * + * 0.32 8/15/01 Changed the tmi_fiber_detect routine. + * + * 0.33 8/16/01 Changed PHY reset method in nic_open routine. Added + * a chip reset in nic_stop to shut down the IPG. + * + * 0.34 9/5/01 Corrected some misuage of dev_kfree_skb. + * + * 0.35 10/30/01 Unmap register space (IO or memory) in the nic_stop + * routine instead of in the cleanup or remove routines. + * Corrects driver up/down/up problem when using IO + * register mapping. + * + * 0.36 10/31/01 Modify the constant IPG_FRAMESBETWEENTXDMACOMPLETES + * from 0x10 to 1. + * 0.37 11/05/03 Modify the IPG_PHY_1000BASETCONTROL + * in IP1000A this register is without 1000BPS Ability by default + * so enable 1000BPS ability before PHY RESET/RESTART_AN + * 0.38 11/05/03 update ipg_config_autoneg routine + * 0.39 11/05/03 add Vendor_ID=13F0/Device_ID=1023 into support_cards + * 2.05 10/16/04 Remove IPG_IE_RFD_LIST_END for pass SmartBit test. + * (see 20041019Jesse_For_SmartBit.) + * 2.06 10/27/04 Support for kernel 2.6.x + * 2.06a 11/03/04 remove some compile warring message. + * 2.09b 06/03/05 Support 4k jumbo (IC Plus, Jesse) + * 2.09d 06/22/05 Support 10k jumbo, more than 4k will using copy mode (IC Plus, Jesse) + */ +#define JUMBO_FRAME_4k_ONLY +enum { + netdev_io_size = 128 +}; + +#include "ipg.h" +#define DRV_NAME "ipg" +/* notify kernel that this software is under GNU Public License */ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) ) + MODULE_LICENSE("GPL"); +#endif + +/* Function prototypes. */ +u16 read_phy_register(IPG_DEVICE_TYPE *ipg_ethernet_device, + int phy_address, int phy_register); +//int ipg_reset(u32 baseaddr, u32 resetflags); //JES20040127EEPROM: change type of param1 +int ipg_reset(IPG_DEVICE_TYPE *ipg_ethernet_device, u32 resetflags); +int ipg_io_config(IPG_DEVICE_TYPE *ipg_ethernet_device); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +void ipg_interrupt_handler(int ipg_irq, void *device_instance, + struct pt_regs *regs); +#else +static irqreturn_t ipg_interrupt_handler(int ipg_irq, void *device_instance, + struct pt_regs *regs); +#endif + +void ipg_nic_txcleanup(IPG_DEVICE_TYPE *ipg_ethernet_device); +void ipg_nic_txfree(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_nic_open(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_nic_stop(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_nic_hard_start_xmit(struct sk_buff *skb, + IPG_DEVICE_TYPE *ipg_ethernet_device); +IPG_STATS_TYPE* ipg_nic_get_stats(IPG_DEVICE_TYPE + *ipg_ethernet_device); +void ipg_nic_set_multicast_list(IPG_DEVICE_TYPE *dev); +int ipg_nic_init(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_nic_rx(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_nic_rxrestore(IPG_DEVICE_TYPE *ipg_ethernet_device); +int init_rfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device); +int init_tfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_get_rxbuff(IPG_DEVICE_TYPE *ipg_ethernet_device, int rfd); +int ipg_sti_fiber_detect(IPG_DEVICE_TYPE *ipg_ethernet_device); +int ipg_tmi_fiber_detect(IPG_DEVICE_TYPE *ipg_ethernet_device, + int phyaddr); +int ipg_config_autoneg(IPG_DEVICE_TYPE *ipg_ethernet_device); +unsigned ether_crc_le(int length, unsigned char *data); +int ipg_nic_do_ioctl(IPG_DEVICE_TYPE *ipg_ethernet_device, + struct ifreq *req, int cmd); +int ipg_nic_change_mtu(IPG_DEVICE_TYPE *ipg_ethernet_device, + int new_mtu); + +#ifdef IPG_LINUX2_2 +int ipg_pcibussearch_linux2_2(void); +#endif + +#ifdef IPG_LINUX2_4 +int ipg_pciprobe_linux2_4(struct pci_dev*, const struct pci_device_id*); +void ipg_pciremove_linux2_4(struct pci_dev*); +#endif + +void bSetPhyDefaultParam(unsigned char Rev, + IPG_DEVICE_TYPE *ipg_ethernet_device,int phy_address); + +//JES20040127EEPROM:Add three new function +int read_eeprom(IPG_DEVICE_TYPE *ipg_ethernet_device, int eep_addr); +void Set_LED_Mode(IPG_DEVICE_TYPE *ipg_ethernet_device); +void Set_PHYSet(IPG_DEVICE_TYPE *ipg_ethernet_device); +/* End function prototypes. */ + +#ifdef IPG_DEBUG +void ipg_dump_rfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + u32 baseaddr; + int i; + u32 offset; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_dump_rfdlist\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + printk(KERN_INFO "CurrentRFD = %2.2x\n", sp->CurrentRFD); + printk(KERN_INFO "LastRestoredRxBuff = %2.2x\n", + sp->LastRestoredRxBuff); +#ifdef IPG_LINUX2_2 + printk(KERN_INFO "RFDList start address = %16.16lx\n", + (unsigned long int)(IPG_HOST2BUS_MAP(sp->RFDList))); +#endif +#ifdef IPG_LINUX2_4 + printk(KERN_INFO "RFDList start address = %16.16lx\n", + (unsigned long int)(sp->RFDListDMAhandle)); +#endif + printk(KERN_INFO "RFDListPtr register = %8.8x%8.8x\n", + IPG_READ_RFDLISTPTR1(baseaddr), + IPG_READ_RFDLISTPTR0(baseaddr)); + + for(i=0;iRFDList[i].RFDNextPtr) + - (u32)(sp->RFDList); + printk(KERN_INFO "%2.2x %4.4x RFDNextPtr = %16.16lx\n", i, + offset, (unsigned long int) sp->RFDList[i].RFDNextPtr); + offset = (u32)(&sp->RFDList[i].RFS) + - (u32)(sp->RFDList); + printk(KERN_INFO "%2.2x %4.4x RFS = %16.16lx\n", i, + offset, (unsigned long int)sp->RFDList[i].RFS); + offset = (u32)(&sp->RFDList[i].FragInfo) + - (u32)(sp->RFDList); + printk(KERN_INFO "%2.2x %4.4x FragInfo = %16.16lx\n", i, + offset, (unsigned long int)sp->RFDList[i].FragInfo); + } + + return; +} + +void ipg_dump_tfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + u32 baseaddr; + int i; + u32 offset; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_dump_tfdlist\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + printk(KERN_INFO "CurrentTFD = %2.2x\n", sp->CurrentTFD); + printk(KERN_INFO "LastFreedTxBuff = %2.2x\n", + sp->LastFreedTxBuff); +#ifdef IPG_LINUX2_2 + printk(KERN_INFO "TFDList start address = %16.16lx\n", + (unsigned long int)(IPG_HOST2BUS_MAP(sp->TFDList))); +#endif +#ifdef IPG_LINUX2_4 + printk(KERN_INFO "TFDList start address = %16.16lx\n", + (unsigned long int)(sp->TFDListDMAhandle)); +#endif + printk(KERN_INFO "TFDListPtr register = %8.8x%8.8x\n", + IPG_READ_TFDLISTPTR1(baseaddr), + IPG_READ_TFDLISTPTR0(baseaddr)); + + for(i=0;iTFDList[i].TFDNextPtr) + - (u32)(sp->TFDList); + printk(KERN_INFO "%2.2x %4.4x TFDNextPtr = %16.16lx\n", i, + offset, (unsigned long int)sp->TFDList[i].TFDNextPtr); + + offset = (u32)(&sp->TFDList[i].TFC) + - (u32)(sp->TFDList); + printk(KERN_INFO "%2.2x %4.4x TFC = %16.16lx\n", i, + offset, (unsigned long int)sp->TFDList[i].TFC); + offset = (u32)(&sp->TFDList[i].FragInfo) + - (u32)(sp->TFDList); + printk(KERN_INFO "%2.2x %4.4x FragInfo = %16.16lx\n", i, + offset, (unsigned long int)sp->TFDList[i].FragInfo); + } + + return; +} +#else /* Not in debug mode. */ +#endif + +void send_three_state(u32 baseaddr, u8 phyctrlpolarity) +{ + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_LO | + (IPG_PC_MGMTDATA & 0) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_HI | + (IPG_PC_MGMTDATA & 0) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + return; +} + +void send_end(u32 baseaddr, u8 phyctrlpolarity) +{ + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_LO | + (IPG_PC_MGMTDATA & 0) | + IPG_PC_MGMTDIR | phyctrlpolarity); + return; +} + + +u16 read_phy_bit(u32 baseaddr, u8 phyctrlpolarity) +{ u16 bit_data; + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_LO | + phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + + bit_data=((IPG_READ_PHYCTRL(baseaddr) & IPG_PC_MGMTDATA) >> 1) & 1; + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_HI | + phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + return bit_data; +} + +u16 read_phy_register(IPG_DEVICE_TYPE *ipg_ethernet_device, + int phy_address, int phy_register) +{ + /* Read a register from the Physical Layer device located + * on the IPG NIC, using the IPG PHYCTRL register. + */ + + u32 baseaddr; + int i; + int j; + int fieldlen[8]; + u32 field[8]; + u8 databit; + u8 phyctrlpolarity; + + IPG_DEBUG_MSG("read_phy_register\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + /* The GMII mangement frame structure for a read is as follows: + * + * |Preamble|st|op|phyad|regad|ta| data |idle| + * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | + * + * <32 1s> = 32 consecutive logic 1 values + * A = bit of Physical Layer device address (MSB first) + * R = bit of register address (MSB first) + * z = High impedance state + * D = bit of read data (MSB first) + * + * Transmission order is 'Preamble' field first, bits transmitted + * left to right (first to last). + */ + + field[0] = GMII_PREAMBLE; + fieldlen[0] = 32; /* Preamble */ + field[1] = GMII_ST; + fieldlen[1] = 2; /* ST */ + field[2] = GMII_READ; + fieldlen[2] = 2; /* OP */ + field[3] = phy_address; + fieldlen[3] = 5; /* PHYAD */ + field[4] = phy_register; + fieldlen[4] = 5; /* REGAD */ + field[5] = 0x0000; + fieldlen[5] = 2; /* TA */ + field[6] = 0x0000; + fieldlen[6] = 16; /* DATA */ + field[7] = 0x0000; + fieldlen[7] = 1; /* IDLE */ + + /* Store the polarity values of PHYCTRL. */ + phyctrlpolarity = IPG_READ_PHYCTRL(baseaddr) & + (IPG_PC_DUPLEX_POLARITY | + IPG_PC_LINK_POLARITY); + + /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ + for(j=0; j<5; j++) + for(i=0; i> (fieldlen[j] - 1 - i)) << 1; + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_LO | + (IPG_PC_MGMTDATA & databit) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_HI | + (IPG_PC_MGMTDATA & databit) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + } + + send_three_state(baseaddr, phyctrlpolarity); + + read_phy_bit(baseaddr, phyctrlpolarity); + + /* For a read cycle, the bits for the next two fields (TA and + * DATA) are driven by the PHY (the IPG reads these bits). + */ +// for(j=6; j<8; j++) + for(i=0; ibase_addr; + + /* The GMII mangement frame structure for a read is as follows: + * + * |Preamble|st|op|phyad|regad|ta| data |idle| + * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | + * + * <32 1s> = 32 consecutive logic 1 values + * A = bit of Physical Layer device address (MSB first) + * R = bit of register address (MSB first) + * z = High impedance state + * D = bit of write data (MSB first) + * + * Transmission order is 'Preamble' field first, bits transmitted + * left to right (first to last). + */ + + field[0] = GMII_PREAMBLE; + fieldlen[0] = 32; /* Preamble */ + field[1] = GMII_ST; + fieldlen[1] = 2; /* ST */ + field[2] = GMII_WRITE; + fieldlen[2] = 2; /* OP */ + field[3] = phy_address; + fieldlen[3] = 5; /* PHYAD */ + field[4] = phy_register; + fieldlen[4] = 5; /* REGAD */ + field[5] = 0x0002; + fieldlen[5] = 2; /* TA */ + field[6] = writeval; + fieldlen[6] = 16; /* DATA */ + field[7] = 0x0000; + fieldlen[7] = 1; /* IDLE */ + + /* Store the polarity values of PHYCTRL. */ + phyctrlpolarity = IPG_READ_PHYCTRL(baseaddr) & + (IPG_PC_DUPLEX_POLARITY | + IPG_PC_LINK_POLARITY); + + /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ + for(j=0; j<7; j++) + for(i=0; i> (fieldlen[j] - 1 - i)) << 1; + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_LO | + (IPG_PC_MGMTDATA & databit) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_HI | + (IPG_PC_MGMTDATA & databit) | + IPG_PC_MGMTDIR | phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + } + + /* The last cycle is a tri-state, so read from the PHY. + */ + for(j=7; j<8; j++) + for(i=0; i> 1) + << (fieldlen[j] - 1 - i); + + IPG_WRITE_PHYCTRL(baseaddr, IPG_PC_MGMTCLK_HI | + phyctrlpolarity); + + mdelay(IPG_PC_PHYCTRLWAIT); + + } + + return; +} +//int ipg_reset(u32 baseaddr, u32 resetflags) //JES20040127EEPROM: change type of param1 +int ipg_reset(IPG_DEVICE_TYPE *ipg_ethernet_device, u32 resetflags) +{ + /* Assert functional resets via the IPG AsicCtrl + * register as specified by the 'resetflags' input + * parameter. + */ + u32 baseaddr;//JES20040127EEPROM: + int timeout_count; + baseaddr = ipg_ethernet_device->base_addr;//JES20040127EEPROM: + + IPG_DEBUG_MSG("_reset\n"); + + IPG_WRITE_ASICCTRL(baseaddr, IPG_READ_ASICCTRL(baseaddr) | + resetflags); + + /* Wait until IPG reset is complete. */ + timeout_count = 0; + + /* Delay added to account for problem with 10Mbps reset. */ + mdelay(IPG_AC_RESETWAIT); + + while (IPG_AC_RESET_BUSY & IPG_READ_ASICCTRL(baseaddr)) + { + mdelay(IPG_AC_RESETWAIT); + timeout_count++; + if (timeout_count > IPG_AC_RESET_TIMEOUT) + return -ETIME; + } + /* Set LED Mode in Asic Control JES20040127EEPROM */ + Set_LED_Mode(ipg_ethernet_device); + + /* Set PHYSet Register Value JES20040127EEPROM */ + Set_PHYSet(ipg_ethernet_device); + return 0; +} + +int ipg_sti_fiber_detect(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Determine if NIC is fiber based by reading the PhyMedia + * bit in the AsicCtrl register. + */ + + u32 asicctrl; + u32 baseaddr; + + IPG_DEBUG_MSG("_sti_fiber_detect\n"); + + baseaddr = ipg_ethernet_device->base_addr; + asicctrl = IPG_READ_ASICCTRL(baseaddr); + + if (asicctrl & IPG_AC_PHY_MEDIA) + { + /* Fiber NIC. */ + return 1; + } else + { + /* Not a fiber NIC. */ + return 0; + } +} + +int ipg_tmi_fiber_detect(IPG_DEVICE_TYPE *ipg_ethernet_device, + int phyaddr) +{ + /* Determine if NIC is fiber based by reading the ID register + * of the PHY and the GMII address. + */ + + u16 phyid; + u32 baseaddr; + + IPG_DEBUG_MSG("_tmi_fiber_detect\n"); + + baseaddr = ipg_ethernet_device->base_addr; + phyid = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_ID_1); + + IPG_DEBUG_MSG("PHY ID = %x\n", phyid); + + /* We conclude the mode is fiber if the GMII address + * is 0x1 and the PHY ID is 0x0000. + */ + if ((phyaddr == 0x1) && (phyid == 0x0000)) + { + /* Fiber NIC. */ + return 1; + } else + { + /* Not a fiber NIC. */ + return 0; + } +} + +int ipg_find_phyaddr(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Find the GMII PHY address. */ + + int i; + int phyaddr; + u32 status; + + for(i=0;i<32;i++) + { + /* Search for the correct PHY address among 32 possible. */ + phyaddr = (IPG_NIC_PHY_ADDRESS + i) % 32; + + /* 10/22/03 Grace change verify from GMII_PHY_STATUS to + GMII_PHY_ID1 + */ + + status = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_STATUS); + + // if (status != 0xFFFF) + if ((status != 0xFFFF) && (status != 0)) + return phyaddr; + + /*---------------------------------------------------- + status = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_ID_1); + if (status == 0x243) { + printk("PHY Addr = %x\n", phyaddr); + return phyaddr; + } + -------------------------------------------------*/ + } + + return -1; +} + +#ifdef NOTGRACE +int ipg_config_autoneg(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Configure IPG based on result of IEEE 802.3 PHY + * auto-negotiation. + */ + + int phyaddr = 0; + u8 phyctrl; + u32 asicctrl; + u32 baseaddr; + u16 status = 0; + u16 advertisement; + u16 linkpartner_ability; + u16 gigadvertisement; + u16 giglinkpartner_ability; + u16 techabilities; + int fiber; + int gig; + int fullduplex; + int txflowcontrol; + int rxflowcontrol; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_config_autoneg\n"); + + baseaddr = ipg_ethernet_device->base_addr; + asicctrl = IPG_READ_ASICCTRL(baseaddr); + phyctrl = IPG_READ_PHYCTRL(baseaddr); + + /* Set flags for use in resolving auto-negotation, assuming + * non-1000Mbps, half duplex, no flow control. + */ + fiber = 0; + fullduplex = 0; + txflowcontrol = 0; + rxflowcontrol = 0; + gig = 0; + + /* To accomodate a problem in 10Mbps operation, + * set a global flag if PHY running in 10Mbps mode. + */ + sp->tenmbpsmode = 0; + + printk("Link speed = "); + + /* Determine actual speed of operation. */ + switch (phyctrl & IPG_PC_LINK_SPEED) + { + case IPG_PC_LINK_SPEED_10MBPS : + printk("10Mbps.\n"); + printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",ipg_ethernet_device->name); + sp->tenmbpsmode = 1; + break; + case IPG_PC_LINK_SPEED_100MBPS : + printk("100Mbps.\n"); + break; + case IPG_PC_LINK_SPEED_1000MBPS : + printk("1000Mbps.\n"); + gig = 1; + break; + default : printk("undefined!\n"); + } + +#ifndef IPG_TMI_FIBER_DETECT + fiber = ipg_sti_fiber_detect(ipg_ethernet_device); + + /* Determine if auto-negotiation resolution is necessary. + * First check for fiber based media 10/100 media. + */ + if ((fiber == 1) && (asicctrl & + (IPG_AC_PHY_SPEED10 | IPG_AC_PHY_SPEED100))) + { + printk(KERN_INFO "%s: Fiber based PHY, setting full duplex, no flow control.\n", ipg_ethernet_device->name); + return -EILSEQ; + IPG_WRITE_MACCTRL(baseaddr, (IPG_READ_MACCTRL(baseaddr) | + IPG_MC_DUPLEX_SELECT_FD) & + ~IPG_MC_TX_FLOW_CONTROL_ENABLE & + ~IPG_MC_RX_FLOW_CONTROL_ENABLE); + + return 0; + } +#endif + + /* Determine if PHY is auto-negotiation capable. */ + phyaddr = ipg_find_phyaddr(ipg_ethernet_device); + + if (phyaddr == -1) + { + printk(KERN_INFO "%s: Error on read to GMII/MII Status register.\n",ipg_ethernet_device->name); + return -EILSEQ; + } + + IPG_DEBUG_MSG("GMII/MII PHY address = %x\n", phyaddr); + + status = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_STATUS); + + printk("PHYStatus = %x \n", status); + if ((status & GMII_PHY_STATUS_AUTONEG_ABILITY) == 0) + { + printk(KERN_INFO "%s: Error PHY unable to perform auto-negotiation.\n", + ipg_ethernet_device->name); + return -EILSEQ; + } + + advertisement = read_phy_register(ipg_ethernet_device, phyaddr, + GMII_PHY_AUTONEGADVERTISEMENT); + linkpartner_ability = read_phy_register(ipg_ethernet_device, phyaddr, + GMII_PHY_AUTONEGLINKPARTABILITY); + + printk("PHYadvertisement=%x LinkPartner=%x \n",advertisement,linkpartner_ability); + if ((advertisement == 0xFFFF) || (linkpartner_ability == 0xFFFF)) + { + printk(KERN_INFO "%s: Error on read to GMII/MII registers 4 and/or 5.\n", ipg_ethernet_device->name); + return -EILSEQ; + } + +#ifdef IPG_TMI_FIBER_DETECT + fiber = ipg_tmi_fiber_detect(ipg_ethernet_device, phyaddr); +#endif + + /* Resolve full/half duplex if 1000BASE-X. */ + if ((gig == 1) && (fiber == 1)) + { + /* Compare the full duplex bits in the GMII registers + * for the local device, and the link partner. If these + * bits are logic 1 in both registers, configure the + * IPG for full duplex operation. + */ + if ((advertisement & GMII_PHY_ADV_FULL_DUPLEX) == + (linkpartner_ability & GMII_PHY_ADV_FULL_DUPLEX)) + { + fullduplex = 1; + + /* In 1000BASE-X using IPG's internal PCS + * layer, so write to the GMII duplex bit. + */ + write_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_CONTROL, + read_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_CONTROL) | + GMII_PHY_CONTROL_FULL_DUPLEX); + + } else + { + fullduplex = 0; + + /* In 1000BASE-X using IPG's internal PCS + * layer, so write to the GMII duplex bit. + */ + write_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_CONTROL, + read_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_CONTROL) & + ~GMII_PHY_CONTROL_FULL_DUPLEX); + } + } + + /* Resolve full/half duplex if 1000BASE-T. */ + if ((gig == 1) && (fiber == 0)) + { + /* Read the 1000BASE-T "Control" and "Status" + * registers which represent the advertised and + * link partner abilities exchanged via next page + * transfers. + */ + gigadvertisement = read_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_1000BASETCONTROL); + giglinkpartner_ability = read_phy_register(ipg_ethernet_device, + phyaddr, + GMII_PHY_1000BASETSTATUS); + + /* Compare the full duplex bits in the 1000BASE-T GMII + * registers for the local device, and the link partner. + * If these bits are logic 1 in both registers, configure + * the IPG for full duplex operation. + */ + if ((gigadvertisement & GMII_PHY_1000BASETCONTROL_FULL_DUPLEX) && + (giglinkpartner_ability & GMII_PHY_1000BASETSTATUS_FULL_DUPLEX)) + { + fullduplex = 1; + } else + { + fullduplex = 0; + } + } + + /* Resolve full/half duplex for 10/100BASE-T. */ + if (gig == 0) + { + /* Autonegotiation Priority Resolution algorithm, as defined in + * IEEE 802.3 Annex 28B. + */ + if (((advertisement & MII_PHY_SELECTORFIELD) == + MII_PHY_SELECTOR_IEEE8023) && + ((linkpartner_ability & MII_PHY_SELECTORFIELD) == + MII_PHY_SELECTOR_IEEE8023)) + { + techabilities = (advertisement & linkpartner_ability & + MII_PHY_TECHABILITYFIELD); + + fullduplex = 0; + + /* 10BASE-TX half duplex is lowest priority. */ + if (techabilities & MII_PHY_TECHABILITY_10BT) + { + fullduplex = 0; + } + + if (techabilities & MII_PHY_TECHABILITY_10BTFD) + { + fullduplex = 1; + } + + if (techabilities & MII_PHY_TECHABILITY_100BTX) + { + fullduplex = 0; + } + + if (techabilities & MII_PHY_TECHABILITY_100BT4) + { + fullduplex = 0; + } + + /* 100BASE-TX half duplex is highest priority. */ //Sorbica full duplex ? + if (techabilities & MII_PHY_TECHABILITY_100BTXFD) + { + fullduplex = 1; + } + + if (fullduplex == 1) + { + /* If in full duplex mode, determine if PAUSE + * functionality is supported by the local + * device, and the link partner. + */ + if (techabilities & MII_PHY_TECHABILITY_PAUSE) + { + txflowcontrol = 1; + rxflowcontrol = 1; + } + else + { + txflowcontrol = 0; + rxflowcontrol = 0; + } + } + } + } + + /* If in 1000Mbps, fiber, and full duplex mode, resolve + * 1000BASE-X PAUSE capabilities. */ + if ((fullduplex == 1) && (fiber == 1) && (gig == 1)) + { + /* In full duplex mode, resolve PAUSE + * functionality. + */ + switch(((advertisement & GMII_PHY_ADV_PAUSE) >> 5) | + ((linkpartner_ability & GMII_PHY_ADV_PAUSE) >> 7)) + { + case 0x7 : + txflowcontrol = 1; + rxflowcontrol = 0; + break; + + case 0xA : case 0xB: case 0xE: case 0xF: + txflowcontrol = 1; + rxflowcontrol = 1; + break; + + case 0xD : + txflowcontrol = 0; + rxflowcontrol = 1; + break; + + default : + txflowcontrol = 0; + rxflowcontrol = 0; + } + } + + /* If in 1000Mbps, non-fiber, full duplex mode, resolve + * 1000BASE-T PAUSE capabilities. */ + if ((fullduplex == 1) && (fiber == 0) && (gig == 1)) + { + /* Make sure the PHY is advertising we are PAUSE + * capable. + */ + if (!(advertisement & (MII_PHY_TECHABILITY_PAUSE | + MII_PHY_TECHABILITY_ASM_DIR))) + { + /* PAUSE is not being advertised. Advertise + * PAUSE and restart auto-negotiation. + */ + write_phy_register(ipg_ethernet_device, + phyaddr, + MII_PHY_AUTONEGADVERTISEMENT, + (advertisement | + MII_PHY_TECHABILITY_PAUSE | + MII_PHY_TECHABILITY_ASM_DIR)); + write_phy_register(ipg_ethernet_device, + phyaddr, + MII_PHY_CONTROL, + MII_PHY_CONTROL_RESTARTAN); + + return -EAGAIN; + } + + /* In full duplex mode, resolve PAUSE + * functionality. + */ + switch(((advertisement & + MII_PHY_TECHABILITY_PAUSE_FIELDS) >> 0x8) | + ((linkpartner_ability & + MII_PHY_TECHABILITY_PAUSE_FIELDS) >> 0xA)) + { + case 0x7 : + txflowcontrol = 1; + rxflowcontrol = 0; + break; + + case 0xA : case 0xB: case 0xE: case 0xF: + txflowcontrol = 1; + rxflowcontrol = 1; + break; + + case 0xD : + txflowcontrol = 0; + rxflowcontrol = 1; + break; + + default : + txflowcontrol = 0; + rxflowcontrol = 0; + } + } + + /* If in 10/100Mbps, non-fiber, full duplex mode, assure + * 10/100BASE-T PAUSE capabilities are advertised. */ + if ((fullduplex == 1) && (fiber == 0) && (gig == 0)) + { + /* Make sure the PHY is advertising we are PAUSE + * capable. + */ + if (!(advertisement & (MII_PHY_TECHABILITY_PAUSE))) + { + /* PAUSE is not being advertised. Advertise + * PAUSE and restart auto-negotiation. + */ + write_phy_register(ipg_ethernet_device, + phyaddr, + MII_PHY_AUTONEGADVERTISEMENT, + (advertisement | + MII_PHY_TECHABILITY_PAUSE)); + write_phy_register(ipg_ethernet_device, + phyaddr, + MII_PHY_CONTROL, + MII_PHY_CONTROL_RESTARTAN); + + return -EAGAIN; + } + + } + + if (fiber == 1) + { + printk(KERN_INFO "%s: Fiber based PHY, ", + ipg_ethernet_device->name); + } else + { + printk(KERN_INFO "%s: Copper based PHY, ", + ipg_ethernet_device->name); + } + + /* Configure full duplex, and flow control. */ + if (fullduplex == 1) + { + /* Configure IPG for full duplex operation. */ + printk("setting full duplex, "); + + IPG_WRITE_MACCTRL(baseaddr, IPG_READ_MACCTRL(baseaddr) | + IPG_MC_DUPLEX_SELECT_FD); + + if (txflowcontrol == 1) + { + printk("TX flow control"); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_TX_FLOW_CONTROL_ENABLE); + } else + { + printk("no TX flow control"); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_TX_FLOW_CONTROL_ENABLE); + } + + if (rxflowcontrol == 1) + { + printk(", RX flow control."); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_RX_FLOW_CONTROL_ENABLE); + } else + { + printk(", no RX flow control."); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_RX_FLOW_CONTROL_ENABLE); + } + + printk("\n"); + } else + { + /* Configure IPG for half duplex operation. */ + printk("setting half duplex, no TX flow control, no RX flow control.\n"); + + IPG_WRITE_MACCTRL(baseaddr, IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_DUPLEX_SELECT_FD & + ~IPG_MC_TX_FLOW_CONTROL_ENABLE & + ~IPG_MC_RX_FLOW_CONTROL_ENABLE); + } + + + IPG_DEBUG_MSG("G/MII reg 4 (advertisement) = %4.4x\n", advertisement); + IPG_DEBUG_MSG("G/MII reg 5 (link partner) = %4.4x\n", linkpartner_ability); + IPG_DEBUG_MSG("G/MII reg 9 (1000BASE-T control) = %4.4x\n", advertisement); + IPG_DEBUG_MSG("G/MII reg 10 (1000BASE-T status) = %4.4x\n", linkpartner_ability); + + IPG_DEBUG_MSG("Auto-neg complete, MACCTRL = %8.8x\n", + IPG_READ_MACCTRL(baseaddr)); + + return 0; +} +#else +int ipg_config_autoneg(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Configure IPG based on result of IEEE 802.3 PHY + * auto-negotiation. + */ + +// int phyaddr = 0; + u8 phyctrl; + u32 asicctrl; + u32 baseaddr; +// u16 status = 0; +// u16 advertisement; +// u16 linkpartner_ability; +// u16 gigadvertisement; +// u16 giglinkpartner_ability; +// u16 techabilities; + int fiber; + int gig; + int fullduplex; + int txflowcontrol; + int rxflowcontrol; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_config_autoneg\n"); + + baseaddr = ipg_ethernet_device->base_addr; + asicctrl = IPG_READ_ASICCTRL(baseaddr); + phyctrl = IPG_READ_PHYCTRL(baseaddr); + + /* Set flags for use in resolving auto-negotation, assuming + * non-1000Mbps, half duplex, no flow control. + */ + fiber = 0; + fullduplex = 0; + txflowcontrol = 0; + rxflowcontrol = 0; + gig = 0; + + /* To accomodate a problem in 10Mbps operation, + * set a global flag if PHY running in 10Mbps mode. + */ + sp->tenmbpsmode = 0; + + printk("Link speed = "); + + /* Determine actual speed of operation. */ + switch (phyctrl & IPG_PC_LINK_SPEED) + { + case IPG_PC_LINK_SPEED_10MBPS : + printk("10Mbps.\n"); + printk(KERN_INFO "%s: 10Mbps operational mode enabled.\n",ipg_ethernet_device->name); + sp->tenmbpsmode = 1; + break; + case IPG_PC_LINK_SPEED_100MBPS : + printk("100Mbps.\n"); + break; + case IPG_PC_LINK_SPEED_1000MBPS : + printk("1000Mbps.\n"); + gig = 1; + break; + default : printk("undefined!\n"); + return 0; + } + + if ( phyctrl & IPG_PC_DUPLEX_STATUS) + { + fullduplex = 1; + txflowcontrol = 1; + rxflowcontrol = 1; + } + else + { + fullduplex = 0; + txflowcontrol = 0; + rxflowcontrol = 0; + } + + + /* Configure full duplex, and flow control. */ + if (fullduplex == 1) + { + /* Configure IPG for full duplex operation. */ + printk("setting full duplex, "); + + IPG_WRITE_MACCTRL(baseaddr, IPG_READ_MACCTRL(baseaddr) | + IPG_MC_DUPLEX_SELECT_FD); + + if (txflowcontrol == 1) + { + printk("TX flow control"); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_TX_FLOW_CONTROL_ENABLE); + } else + { + printk("no TX flow control"); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_TX_FLOW_CONTROL_ENABLE); + } + + if (rxflowcontrol == 1) + { + printk(", RX flow control."); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_RX_FLOW_CONTROL_ENABLE); + } else + { + printk(", no RX flow control."); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_RX_FLOW_CONTROL_ENABLE); + } + + printk("\n"); + } else + { + /* Configure IPG for half duplex operation. */ + printk("setting half duplex, no TX flow control, no RX flow control.\n"); + + IPG_WRITE_MACCTRL(baseaddr, IPG_READ_MACCTRL(baseaddr) & + ~IPG_MC_DUPLEX_SELECT_FD & + ~IPG_MC_TX_FLOW_CONTROL_ENABLE & + ~IPG_MC_RX_FLOW_CONTROL_ENABLE); + } + return 0; +} + +#endif + +int ipg_io_config(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Initialize the IPG I/O registers. */ + + u32 baseaddr; + u32 origmacctrl; + u32 restoremacctrl; + + IPG_DEBUG_MSG("_io_config\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + /* Save the original value of MACCTRL. */ + origmacctrl = IPG_READ_MACCTRL(baseaddr); + + /* Establish a vlaue to restore MACCTRL when done. */ + restoremacctrl = origmacctrl; + + /* Enable statistics gathering. */ + restoremacctrl |= IPG_MC_STATISTICS_ENABLE; + + /* Based on compilation option, determine if FCS is to be + * stripped on receive frames by IPG. + */ + if (!(IPG_STRIP_FCS_ON_RX)) + { + restoremacctrl |= IPG_MC_RCV_FCS; + } + + /* Determine if transmitter and/or receiver are + * enabled so we may restore MACCTRL correctly. + */ + if (origmacctrl & IPG_MC_TX_ENABLED) + { + restoremacctrl |= IPG_MC_TX_ENABLE; + } + + if (origmacctrl & IPG_MC_RX_ENABLED) + { + restoremacctrl |= IPG_MC_RX_ENABLE; + } + + /* Transmitter and receiver must be disabled before setting + * IFSSelect. + */ + IPG_WRITE_MACCTRL(baseaddr, origmacctrl & (IPG_MC_RX_DISABLE | + IPG_MC_TX_DISABLE)); + + /* Now that transmitter and receiver are disabled, write + * to IFSSelect. + */ + IPG_WRITE_MACCTRL(baseaddr, origmacctrl & IPG_MC_IFS_96BIT); + + /* Set RECEIVEMODE register. */ + ipg_nic_set_multicast_list(ipg_ethernet_device); + + IPG_WRITE_MAXFRAMESIZE(baseaddr, IPG_MAX_RXFRAME_SIZE); + IPG_WRITE_RXEARLYTHRESH(baseaddr, IPG_RXEARLYTHRESH_VALUE); + IPG_WRITE_TXSTARTTHRESH(baseaddr, IPG_TXSTARTTHRESH_VALUE); + IPG_WRITE_RXDMAINTCTRL(baseaddr, (IPG_RI_RSVD_MASK & + ((IPG_RI_RXFRAME_COUNT & + IPG_RXFRAME_COUNT) | + (IPG_RI_PRIORITY_THRESH & + (IPG_PRIORITY_THRESH << 12)) | + (IPG_RI_RXDMAWAIT_TIME & + (IPG_RXDMAWAIT_TIME << 16))))); + IPG_WRITE_RXDMAPOLLPERIOD(baseaddr, IPG_RXDMAPOLLPERIOD_VALUE); + IPG_WRITE_RXDMAURGENTTHRESH(baseaddr, + IPG_RXDMAURGENTTHRESH_VALUE); + IPG_WRITE_RXDMABURSTTHRESH(baseaddr, + IPG_RXDMABURSTTHRESH_VALUE); + IPG_WRITE_TXDMAPOLLPERIOD(baseaddr, + IPG_TXDMAPOLLPERIOD_VALUE); + IPG_WRITE_TXDMAURGENTTHRESH(baseaddr, + IPG_TXDMAURGENTTHRESH_VALUE); + IPG_WRITE_TXDMABURSTTHRESH(baseaddr, + IPG_TXDMABURSTTHRESH_VALUE); + IPG_WRITE_INTENABLE(baseaddr, IPG_IE_HOST_ERROR | + IPG_IE_TX_DMA_COMPLETE | + IPG_IE_TX_COMPLETE | + IPG_IE_INT_REQUESTED | + IPG_IE_UPDATE_STATS | + IPG_IE_LINK_EVENT | + IPG_IE_RX_DMA_COMPLETE | + //IPG_IE_RFD_LIST_END | //20041019Jesse_For_SmartBit: remove + IPG_IE_RX_DMA_PRIORITY); + + IPG_WRITE_FLOWONTHRESH(baseaddr, IPG_FLOWONTHRESH_VALUE); + IPG_WRITE_FLOWOFFTHRESH(baseaddr, IPG_FLOWOFFTHRESH_VALUE); + + /* IPG multi-frag frame bug workaround. + * Per silicon revision B3 eratta. + */ + IPG_WRITE_DEBUGCTRL(baseaddr, + IPG_READ_DEBUGCTRL(baseaddr) | 0x0200); + + /* IPG TX poll now bug workaround. + * Per silicon revision B3 eratta. + */ + IPG_WRITE_DEBUGCTRL(baseaddr, + IPG_READ_DEBUGCTRL(baseaddr) | 0x0010); + + /* IPG RX poll now bug workaround. + * Per silicon revision B3 eratta. + */ + IPG_WRITE_DEBUGCTRL(baseaddr, + IPG_READ_DEBUGCTRL(baseaddr) | 0x0020); + + /* Now restore MACCTRL to original setting. */ + IPG_WRITE_MACCTRL(baseaddr, restoremacctrl); + + /* Disable unused RMON statistics. */ + IPG_WRITE_RMONSTATISTICSMASK(baseaddr, IPG_RZ_ALL); + + /* Disable unused MIB statistics. */ + IPG_WRITE_STATISTICSMASK(baseaddr, + IPG_SM_MACCONTROLFRAMESXMTD | + IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK | + IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK | + IPG_SM_MACCONTROLFRAMESRCVD | + IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK | + IPG_SM_TXJUMBOFRAMES | + IPG_SM_UDPCHECKSUMERRORS | + IPG_SM_IPCHECKSUMERRORS | + IPG_SM_TCPCHECKSUMERRORS | + IPG_SM_RXJUMBOFRAMES); + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +void ipg_interrupt_handler(int ipg_irq, void *device_instance, + struct pt_regs *regs) +#else +static irqreturn_t ipg_interrupt_handler(int ipg_irq, void *device_instance, + struct pt_regs *regs) +#endif +{ + int error; + u32 baseaddr; + u16 intstatusackword; + IPG_DEVICE_TYPE *ipg_ethernet_device = + (IPG_DEVICE_TYPE *)device_instance; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + irqreturn_t intr_handled= IRQ_HANDLED;//IRQ_NONE; +#endif + +#ifdef IPG_DEBUG + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; +#endif + + IPG_DEBUG_MSG("_interrupt_handler\n"); + + baseaddr = ipg_ethernet_device->base_addr; + +#ifdef IPG_LINUX2_2 + /* + * The following code fragment was authored by Donald Becker. + */ +#if defined(__i386__) + /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ + if (test_and_set_bit(0, (void*)&ipg_ethernet_device->interrupt)) { + printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n", + ipg_ethernet_device->name); + ipg_ethernet_device->interrupt = 0; /* Avoid halting machine. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return intr_handled; +#else + return; +#endif + + } +#else + if (ipg_ethernet_device->interrupt) { + printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", + ipg_ethernet_device->name); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return intr_handled; +#else + return; +#endif + } + ipg_ethernet_device->interrupt = 1; +#endif + /* + * End of code fragment authored by Donald Becker. + */ + + /* Setting ipg_ethernet_device->interrupt = 1 + * indicates to higher network layers an + * Ethernet NIC interrupt is being serviced. + */ +#endif + +#ifdef JUMBO_FRAME + ipg_nic_rxrestore(ipg_ethernet_device); +#endif + /* Get interrupt source information, and acknowledge + * some (i.e. TxDMAComplete, RxDMAComplete, RxEarly, + * IntRequested, MacControlFrame, LinkEvent) interrupts + * if issued. Also, all IPG interrupts are disabled by + * reading IntStatusAck. + */ + intstatusackword = IPG_READ_INTSTATUSACK(baseaddr); + + IPG_DEBUG_MSG("IntStatusAck = %4.4x\n", intstatusackword); + + /* If RFDListEnd interrupt, restore all used RFDs. */ + if (intstatusackword & IPG_IS_RFD_LIST_END) + { + IPG_DEBUG_MSG("RFDListEnd Interrupt.\n"); + + /* The RFD list end indicates an RFD was encountered + * with a 0 NextPtr, or with an RFDDone bit set to 1 + * (indicating the RFD is not read for use by the + * IPG.) Try to restore all RFDs. + */ + ipg_nic_rxrestore(ipg_ethernet_device); + +#ifdef IPG_DEBUG + /* Increment the RFDlistendCount counter. */ + sp->RFDlistendCount++; +#endif + } + + /* If RFDListEnd, RxDMAPriority, RxDMAComplete, or + * IntRequested interrupt, process received frames. */ + if ((intstatusackword & IPG_IS_RX_DMA_PRIORITY) || + (intstatusackword & IPG_IS_RFD_LIST_END) || + (intstatusackword & IPG_IS_RX_DMA_COMPLETE) || + (intstatusackword & IPG_IS_INT_REQUESTED)) + { + +#ifdef IPG_DEBUG + /* Increment the RFD list checked counter if interrupted + * only to check the RFD list. */ + if (intstatusackword & (~(IPG_IS_RX_DMA_PRIORITY | + IPG_IS_RFD_LIST_END | IPG_IS_RX_DMA_COMPLETE | + IPG_IS_INT_REQUESTED) & + (IPG_IS_HOST_ERROR | + IPG_IS_TX_DMA_COMPLETE | + IPG_IS_TX_COMPLETE | + IPG_IS_UPDATE_STATS | + IPG_IS_LINK_EVENT))) + + { + sp->RFDListCheckedCount++; + } +#endif + + ipg_nic_rx(ipg_ethernet_device); + } + + /* If TxDMAComplete interrupt, free used TFDs. */ + if (intstatusackword & IPG_IS_TX_DMA_COMPLETE) + { + /* Free used TFDs. */ + ipg_nic_txfree(ipg_ethernet_device); + } + + /* TxComplete interrupts indicate one of numerous actions. + * Determine what action to take based on TXSTATUS register. + */ + if (intstatusackword & IPG_IS_TX_COMPLETE) + { + ipg_nic_txcleanup(ipg_ethernet_device); + } + + /* If UpdateStats interrupt, update Linux Ethernet statistics */ + if (intstatusackword & IPG_IS_UPDATE_STATS) + { + ipg_nic_get_stats(ipg_ethernet_device); + } + + /* If HostError interrupt, reset IPG. */ + if (intstatusackword & IPG_IS_HOST_ERROR) + { + IPG_DDEBUG_MSG("HostError Interrupt\n"); + + IPG_DDEBUG_MSG("DMACtrl = %8.8x\n", + IPG_READ_DMACTRL(baseaddr)); + + /* Acknowledge HostError interrupt by resetting + * IPG DMA and HOST. + */ + ipg_reset(ipg_ethernet_device, + IPG_AC_GLOBAL_RESET | + IPG_AC_HOST | + IPG_AC_DMA); + + error = ipg_io_config(ipg_ethernet_device); + if (error < 0) + { + printk(KERN_INFO "%s: Cannot recover from PCI error.\n", + ipg_ethernet_device->name); + } + + init_rfdlist(ipg_ethernet_device); + + init_tfdlist(ipg_ethernet_device); + } + + /* If LinkEvent interrupt, resolve autonegotiation. */ + if (intstatusackword & IPG_IS_LINK_EVENT) + { + if (ipg_config_autoneg(ipg_ethernet_device) < 0) + printk(KERN_INFO "%s: Auto-negotiation error.\n", + ipg_ethernet_device->name); + + } + + /* If MACCtrlFrame interrupt, do nothing. */ + if (intstatusackword & IPG_IS_MAC_CTRL_FRAME) + { + IPG_DEBUG_MSG("MACCtrlFrame interrupt.\n"); + } + + /* If RxComplete interrupt, do nothing. */ + if (intstatusackword & IPG_IS_RX_COMPLETE) + { + IPG_DEBUG_MSG("RxComplete interrupt.\n"); + } + + /* If RxEarly interrupt, do nothing. */ + if (intstatusackword & IPG_IS_RX_EARLY) + { + IPG_DEBUG_MSG("RxEarly interrupt.\n"); + } + + /* Re-enable IPG interrupts. */ + IPG_WRITE_INTENABLE(baseaddr, IPG_IE_HOST_ERROR | + IPG_IE_TX_DMA_COMPLETE | + IPG_IE_TX_COMPLETE | + IPG_IE_INT_REQUESTED | + IPG_IE_UPDATE_STATS | + IPG_IE_LINK_EVENT | + IPG_IE_RX_DMA_COMPLETE | + //IPG_IE_RFD_LIST_END | //20041019Jesse_For_SmartBit: remove + IPG_IE_RX_DMA_PRIORITY); + + /* Indicate to higher network layers the Ethernet NIC + * interrupt servicing is complete. + */ + +#ifdef IPG_LINUX2_2 + /* + * The following code fragment was authored by Donald Becker. + */ +#if defined(__i386__) + clear_bit(0, (void*)&ipg_ethernet_device->interrupt); +#else + ipg_ethernet_device->interrupt = 0; +#endif + /* + * End of code fragment authored by Donald Becker. + */ +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return intr_handled; +#else + return; +#endif +} + +void ipg_nic_txcleanup(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* For TxComplete interrupts, free all transmit + * buffers which have already been transfered via DMA + * to the IPG. + */ + + int maxtfdcount; + u32 baseaddr; + u32 txstatusdword; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_txcleanup\n"); + + baseaddr = ipg_ethernet_device->base_addr; + maxtfdcount = IPG_TFDLIST_LENGTH; + + do + { + /* Reading the TXSTATUS register clears the + * TX_COMPLETE interrupt. + */ + txstatusdword = IPG_READ_TXSTATUS(baseaddr); + + IPG_DEBUG_MSG("TxStatus = %8.8x\n",txstatusdword); + + /* Check for Transmit errors. Error bits only valid if + * TX_COMPLETE bit in the TXSTATUS register is a 1. + */ + if (txstatusdword & IPG_TS_TX_COMPLETE) + { + + /* If in 10Mbps mode, indicate transmit is ready. */ + if (sp->tenmbpsmode) + { + spin_lock(&sp->lock); + IPG_TX_NOTBUSY(ipg_ethernet_device); + spin_unlock(&sp->lock); + } + + /* Transmit error, increment stat counters. */ + if (txstatusdword & IPG_TS_TX_ERROR) + { + IPG_DEBUG_MSG("Transmit error.\n"); + sp->stats.tx_errors++; + } + + /* Late collision, re-enable transmitter. */ + if (txstatusdword & IPG_TS_LATE_COLLISION) + { + IPG_DEBUG_MSG("Late collision on transmit.\n"); + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_TX_ENABLE); + } + + /* Maximum collisions, re-enable transmitter. */ + if (txstatusdword & IPG_TS_TX_MAX_COLL) + { + IPG_DEBUG_MSG("Maximum collisions on transmit.\n"); + + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_TX_ENABLE); + } + + /* Transmit underrun, reset and re-enable + * transmitter. + */ + if (txstatusdword & IPG_TS_TX_UNDERRUN) + { + IPG_DEBUG_MSG("Transmitter underrun.\n"); + sp->stats.tx_fifo_errors++; + ipg_reset(ipg_ethernet_device, IPG_AC_TX_RESET | + IPG_AC_DMA | + IPG_AC_NETWORK); + + /* Re-configure after DMA reset. */ + if ((ipg_io_config(ipg_ethernet_device) < 0) || + (init_tfdlist(ipg_ethernet_device) < 0)) + { + printk(KERN_INFO "%s: Error during re-configuration.\n", + ipg_ethernet_device->name); + } + + IPG_WRITE_MACCTRL(baseaddr, + IPG_READ_MACCTRL(baseaddr) | + IPG_MC_TX_ENABLE); + } + } + else + break; + + maxtfdcount--; + + } + while(maxtfdcount != 0); + + ipg_nic_txfree(ipg_ethernet_device); + + return; +} + +void ipg_nic_txfree(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Free all transmit buffers which have already been transfered + * via DMA to the IPG. + */ + + int NextToFree; + int maxtfdcount; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_txfree\n"); + + maxtfdcount = IPG_TFDLIST_LENGTH; + + /* Set the CurrentTxFrameID to skip the next + * TxDMACompleteInterrupt. + */ + sp->CurrentTxFrameID = 1; + + do + { + /* Calculate next TFD to release. */ + NextToFree = (sp->LastFreedTxBuff + 1) % IPG_TFDLIST_LENGTH; + + IPG_DEBUG_MSG("TFC = %16.16lx\n", (unsigned long int) + sp->TFDList[NextToFree].TFC); + + /* Look at each TFD's TFC field beginning + * at the last freed TFD up to the current TFD. + * If the TFDDone bit is set, free the associated + * buffer. + */ + if ((le64_to_cpu(sp->TFDList[NextToFree].TFC) & + IPG_TFC_TFDDONE) && + (NextToFree != sp->CurrentTFD)) + { + /* Free the transmit buffer. */ + if (sp->TxBuff[NextToFree] != NULL) + { +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device, + sp->TxBuffDMAhandle[NextToFree].dmahandle, + sp->TxBuffDMAhandle[NextToFree].len, + PCI_DMA_TODEVICE); +#endif + + IPG_DEV_KFREE_SKB(sp->TxBuff[NextToFree]); + + sp->TxBuff[NextToFree] = NULL; + } + + sp->LastFreedTxBuff = NextToFree; + } + else + break; + + maxtfdcount--; + + } while(maxtfdcount != 0); + + return; +} + +int ipg_nic_open(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* The IPG NIC Ethernet interface is opened when activated + * by ifconfig. + */ + + int phyaddr = 0; + int error = 0; + int i; + u32 baseaddr; + u8 revisionid=0; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_open\n"); + + + +#ifdef USE_IO_OPS +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* Check for I/O port address conflicts, return error + * if requested range is already in use. + */ + if ((error = check_region(IPG_PCI_RESOURCE_START( + sp->ipg_pci_device, 0) & + IPG_PIB_IOBASEADDRESS, + IPG_IO_REG_RANGE)) < 0) + { + printk(KERN_INFO "%s: Error registering I/O ports.\n", + ipg_ethernet_device->name); + return error; + } + + /* Requested range is free, reserve that range for + * use by the IPG. + */ + request_region(IPG_PCI_RESOURCE_START(sp->ipg_pci_device, 0) & + IPG_PIB_IOBASEADDRESS, + IPG_IO_REG_RANGE, + IPG_DRIVER_NAME); + + /* Use I/O space to access IPG registers. */ + ipg_ethernet_device->base_addr = + (IPG_PCI_RESOURCE_START(sp->ipg_pci_device, 0) & + IPG_PIB_IOBASEADDRESS); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + +#else /* Not using I/O space. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* Use memory space to access IPG registers. ioremap + * is used to map high-memory PCI buffer address space + * to user address space. + */ + ipg_ethernet_device->base_addr = (unsigned long) + (ioremap(IPG_PCI_RESOURCE_START(sp->ipg_pci_device, 1) & + IPG_PMB_MEMBASEADDRESS, IPG_MEM_REG_RANGE)); +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#ifdef IPG_LINUX2_4 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + ipg_ethernet_device->mem_start = pci_resource_start( + sp->ipg_pci_device, 1); + ipg_ethernet_device->mem_end = ipg_ethernet_device->mem_start + IPG_MEM_REG_RANGE; +#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#endif + +#endif + + baseaddr = ipg_ethernet_device->base_addr; + + /* Reset all functions within the IPG. Do not assert + * RST_OUT as not compatible with some PHYs. + */ + i = IPG_AC_GLOBAL_RESET | IPG_AC_RX_RESET | + IPG_AC_TX_RESET | IPG_AC_DMA | + IPG_AC_FIFO | IPG_AC_NETWORK | + IPG_AC_HOST | IPG_AC_AUTO_INIT; + /* Read/Write and Reset EEPROM Value Jesse20040128EEPROM_VALUE */ + /* Read LED Mode Configuration from EEPROM */ + sp->LED_Mode=read_eeprom(ipg_ethernet_device, 6); + + error = ipg_reset(ipg_ethernet_device, i); + if (error < 0) + { + return error; + } + + /* Reset PHY. */ + phyaddr = ipg_find_phyaddr(ipg_ethernet_device); + + if (phyaddr != -1) + { u16 mii_phyctrl, mii_1000cr; + mii_1000cr = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_1000BASETCONTROL); + write_phy_register(ipg_ethernet_device, phyaddr, + GMII_PHY_1000BASETCONTROL, + mii_1000cr | + GMII_PHY_1000BASETCONTROL_FULL_DUPLEX | + GMII_PHY_1000BASETCONTROL_HALF_DUPLEX | + GMII_PHY_1000BASETCONTROL_PreferMaster); + + mii_phyctrl = read_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_CONTROL); + /* Set default phyparam*/ + pci_read_config_byte(sp->ipg_pci_device,PCI_REVISION_ID,&revisionid); + bSetPhyDefaultParam(revisionid,ipg_ethernet_device,phyaddr); + + /* reset Phy*/ + write_phy_register(ipg_ethernet_device, + phyaddr, GMII_PHY_CONTROL, + (mii_phyctrl | GMII_PHY_CONTROL_RESET | + MII_PHY_CONTROL_RESTARTAN)); + + } + + /* Intitalize lock variable before requesting interrupt. */ + sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + + /* Check for interrupt line conflicts, and request interrupt + * line for IPG. + * + * IMPORTANT: Disable IPG interrupts prior to registering + * IRQ. + */ + IPG_WRITE_INTENABLE(baseaddr, 0x0000); + + /* Register the interrupt line to be used by the IPG within + * the Linux system. + */ + if ((error = request_irq(sp->ipg_pci_device->irq, + &ipg_interrupt_handler, + SA_SHIRQ, + ipg_ethernet_device->name, + ipg_ethernet_device)) < 0) + { + printk(KERN_INFO "%s: Error when requesting interrupt.\n", + ipg_ethernet_device->name); + return error; + } + + ipg_ethernet_device->irq = sp->ipg_pci_device->irq; + +#ifdef IPG_LINUX2_2 + /* Reserve memory for RFD list which must lie on an 8 byte + * boundary. So, allocated memory must be adjusted to account + * for this alignment. + */ + sp->RFDList = kmalloc((sizeof(struct RFD) * IPG_RFDLIST_LENGTH) + + IPG_DMALIST_ALIGN_PAD, GFP_KERNEL); + + if (sp->RFDList != NULL) + { + /* Adjust the start address of the allocated + * memory to assure it begins on an 8 byte + * boundary. + */ + sp->RFDList = (void *)(((long)(sp->RFDList) + + IPG_DMALIST_ALIGN_PAD) & + ~IPG_DMALIST_ALIGN_PAD); + } + + /* Reserve memory for TFD list which must lie on an 8 byte + * boundary. So, allocated memory must be adjusted to account + * for this alignment. + */ + sp->TFDList = kmalloc((sizeof(struct TFD) * IPG_TFDLIST_LENGTH) + + IPG_DMALIST_ALIGN_PAD, GFP_KERNEL); + + if (sp->TFDList != NULL) + { + /* Adjust the start address of the allocated + * memory to assure it begins on an 8 byte + * boundary. + */ + sp->TFDList = (void *)(((long)(sp->TFDList) + + IPG_DMALIST_ALIGN_PAD) & + ~IPG_DMALIST_ALIGN_PAD); + } +#endif + +#ifdef IPG_LINUX2_4 + sp->RFDList = pci_alloc_consistent(sp->ipg_pci_device, + (sizeof(struct RFD) * + IPG_RFDLIST_LENGTH), + &sp->RFDListDMAhandle); + + sp->TFDList = pci_alloc_consistent(sp->ipg_pci_device, + (sizeof(struct TFD) * + IPG_TFDLIST_LENGTH), + &sp->TFDListDMAhandle); +#endif + + if ((sp->RFDList == NULL) || (sp->TFDList == NULL)) + { + printk(KERN_INFO "%s: No memory available for IP1000 RFD and/or TFD lists.\n", ipg_ethernet_device->name); + return -ENOMEM; + } + + error = init_rfdlist(ipg_ethernet_device); + if (error < 0) + { + printk(KERN_INFO "%s: Error during configuration.\n", + ipg_ethernet_device->name); + return error; + } + + error = init_tfdlist(ipg_ethernet_device); + if (error < 0) + { + printk(KERN_INFO "%s: Error during configuration.\n", + ipg_ethernet_device->name); + return error; + } + + /* Read MAC Address from EERPOM Jesse20040128EEPROM_VALUE */ + sp->StationAddr0=read_eeprom(ipg_ethernet_device, 16); + sp->StationAddr1=read_eeprom(ipg_ethernet_device, 17); + sp->StationAddr2=read_eeprom(ipg_ethernet_device, 18); + /* Write MAC Address to Station Address */ + IPG_WRITE_STATIONADDRESS0(baseaddr,sp->StationAddr0); + IPG_WRITE_STATIONADDRESS1(baseaddr,sp->StationAddr1); + IPG_WRITE_STATIONADDRESS2(baseaddr,sp->StationAddr2); + + /* Set station address in ethernet_device structure. */ + ipg_ethernet_device->dev_addr[0] = + IPG_READ_STATIONADDRESS0(baseaddr) & 0x00FF; + ipg_ethernet_device->dev_addr[1] = + (IPG_READ_STATIONADDRESS0(baseaddr) & 0xFF00) >> 8; + ipg_ethernet_device->dev_addr[2] = + IPG_READ_STATIONADDRESS1(baseaddr) & 0x00FF; + ipg_ethernet_device->dev_addr[3] = + (IPG_READ_STATIONADDRESS1(baseaddr) & 0xFF00) >> 8; + ipg_ethernet_device->dev_addr[4] = + IPG_READ_STATIONADDRESS2(baseaddr) & 0x00FF; + ipg_ethernet_device->dev_addr[5] = + (IPG_READ_STATIONADDRESS2(baseaddr) & 0xFF00) >> 8; + + /* Configure IPG I/O registers. */ + error = ipg_io_config(ipg_ethernet_device); + if (error < 0) + { + printk(KERN_INFO "%s: Error during configuration.\n", + ipg_ethernet_device->name); + return error; + } + + /* Resolve autonegotiation. */ + if (ipg_config_autoneg(ipg_ethernet_device) < 0) + { + printk(KERN_INFO "%s: Auto-negotiation error.\n", + ipg_ethernet_device->name); + } + +#ifdef JUMBO_FRAME + /* initialize JUMBO Frame control variable */ + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=0; + ipg_ethernet_device->mtu = IPG_TXFRAG_SIZE; +#endif + + /* Enable transmit and receive operation of the IPG. */ + IPG_WRITE_MACCTRL(baseaddr, IPG_READ_MACCTRL(baseaddr) | + IPG_MC_RX_ENABLE | IPG_MC_TX_ENABLE); + +#ifdef IPG_LINUX2_2 + ipg_ethernet_device->interrupt = 0; + ipg_ethernet_device->start = 1; + clear_bit(0,(void*)&ipg_ethernet_device->tbusy); +#endif + +#ifdef IPG_LINUX2_4 + netif_start_queue(ipg_ethernet_device); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* Increment the usage count for this IPG driver module. */ + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +int init_rfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Initialize the RFDList. */ + + int i; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_init_rfdlist\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + /* Clear the receive buffer not ready flag. */ + sp->RxBuffNotReady = 0; + + for(i=0; iipg_pci_device, + sp->RxBuffDMAhandle[i].dmahandle, + sp->RxBuffDMAhandle[i].len, + PCI_DMA_FROMDEVICE); +#endif + if (sp->RxBuff[i] != NULL) + IPG_DEV_KFREE_SKB(sp->RxBuff[i]); + sp->RxBuff[i] = NULL; + + /* Clear out the RFS field. */ + sp->RFDList[i].RFS = 0x0000000000000000; + + if (ipg_get_rxbuff(ipg_ethernet_device, i) < 0) + { + /* A receive buffer was not ready, break the + * RFD list here and set the receive buffer + * not ready flag. + */ + sp->RxBuffNotReady = 1; + + IPG_DEBUG_MSG("Cannot allocate Rx buffer.\n"); + + /* Just in case we cannot allocate a single RFD. + * Should not occur. + */ + if (i == 0) + { + printk(KERN_ERR "%s: No memory available for RFD list.\n", + ipg_ethernet_device->name); + return -ENOMEM; + } + } + + /* Set up RFDs to point to each other. A ring structure. */ +#ifdef IPG_LINUX2_2 + sp->RFDList[i].RFDNextPtr = cpu_to_le64( + IPG_HOST2BUS_MAP( + &sp->RFDList[(i + 1) % + IPG_RFDLIST_LENGTH])); +#endif + +#ifdef IPG_LINUX2_4 + sp->RFDList[i].RFDNextPtr = cpu_to_le64( + sp->RFDListDMAhandle + + ((sizeof(struct RFD)) * + ((i + 1) % + IPG_RFDLIST_LENGTH))); +#endif + } + + sp->CurrentRFD = 0; + sp->LastRestoredRxBuff = i - 1; + + /* Write the location of the RFDList to the IPG. */ +#ifdef IPG_LINUX2_2 + IPG_WRITE_RFDLISTPTR0(baseaddr, + (u32)(IPG_HOST2BUS_MAP(sp->RFDList))); + IPG_WRITE_RFDLISTPTR1(baseaddr, 0x00000000); +#endif + +#ifdef IPG_LINUX2_4 + IPG_WRITE_RFDLISTPTR0(baseaddr, (u32)(sp->RFDListDMAhandle)); + IPG_WRITE_RFDLISTPTR1(baseaddr, 0x00000000); +#endif + + return 0; +} + +int init_tfdlist(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Initialize TFDList. */ + + int i; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_init_tfdlist\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + for(i=0; iTFDList[i].TFDNextPtr = cpu_to_le64( + IPG_HOST2BUS_MAP( + &sp->TFDList[(i + 1) % + IPG_TFDLIST_LENGTH])); +#endif + +#ifdef IPG_LINUX2_4 + sp->TFDList[i].TFDNextPtr = cpu_to_le64( + sp->TFDListDMAhandle + + ((sizeof(struct TFD)) * + ((i + 1) % + IPG_TFDLIST_LENGTH))); +#endif + + sp->TFDList[i].TFC = cpu_to_le64(IPG_TFC_TFDDONE); + if (sp->TxBuff[i] != NULL) + IPG_DEV_KFREE_SKB(sp->TxBuff[i]); + sp->TxBuff[i] = NULL; + } + + sp->CurrentTFD = IPG_TFDLIST_LENGTH - 1; + sp->CurrentTxFrameID = 0; + sp->LastFreedTxBuff = IPG_TFDLIST_LENGTH - 1; + + /* Write the location of the TFDList to the IPG. */ +#ifdef IPG_LINUX2_2 + IPG_WRITE_TFDLISTPTR0(baseaddr, (u32)(IPG_HOST2BUS_MAP( + sp->TFDList))); + IPG_WRITE_TFDLISTPTR1(baseaddr, 0x00000000); +#endif + +#ifdef IPG_LINUX2_4 + IPG_DDEBUG_MSG("Starting TFDListPtr = %8.8x\n", + (u32)(sp->TFDListDMAhandle)); + IPG_WRITE_TFDLISTPTR0(baseaddr, (u32)(sp->TFDListDMAhandle)); + IPG_WRITE_TFDLISTPTR1(baseaddr, 0x00000000); +#endif + + return 0; +} + +int ipg_get_rxbuff(IPG_DEVICE_TYPE *ipg_ethernet_device, int rfd) +{ + /* Create a receive buffer within system memory and update + * NIC private structure appropriately. + */ + u64 rxfragsize; + struct sk_buff *skb; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_get_rxbuff\n"); + + /* Allocate memory buffers for receive frames. Pad by + * 2 to account for IP field alignment. + */ + skb = dev_alloc_skb(IPG_RXSUPPORT_SIZE + 2); + + if (skb == NULL) + { + sp->RxBuff[rfd] = NULL; + return -ENOMEM; + } + + /* Adjust the data start location within the buffer to + * align IP address field to a 16 byte boundary. + */ + skb_reserve(skb, 2); + + /* Associate the receive buffer with the IPG NIC. */ + skb->dev = ipg_ethernet_device; + + /* Save the address of the sk_buff structure. */ + sp->RxBuff[rfd] = skb; + +#ifdef IPG_LINUX2_2 + /* The sk_buff struct "data" field holds the address + * of the beginning of valid octets. Assign this address + * to the fragement address field of the RFD. + */ + sp->RFDList[rfd].FragInfo = cpu_to_le64( + IPG_HOST2BUS_MAP(skb->data)); +#endif + +#ifdef IPG_LINUX2_4 + sp->RxBuffDMAhandle[rfd].len = IPG_RXSUPPORT_SIZE; + sp->RxBuffDMAhandle[rfd].dmahandle = pci_map_single( + sp->ipg_pci_device, + skb->data, IPG_RXSUPPORT_SIZE, + PCI_DMA_FROMDEVICE); + sp->RFDList[rfd].FragInfo = cpu_to_le64( + sp->RxBuffDMAhandle[rfd].dmahandle); +#endif + + /* Set the RFD fragment length. */ + rxfragsize = IPG_RXFRAG_SIZE; + sp->RFDList[rfd].FragInfo |= cpu_to_le64((rxfragsize << 48) & + IPG_RFI_FRAGLEN); + + return 0; +} + +int ipg_nic_stop(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Release resources requested by driver open function. */ + + int i; + int error; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_stop\n"); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + netif_stop_queue(ipg_ethernet_device); + //netif_msg_ifdown(sp); +#endif + + baseaddr = ipg_ethernet_device->base_addr; + + IPG_DDEBUG_MSG("TFDunavailCount = %i\n", sp->TFDunavailCount); + IPG_DDEBUG_MSG("RFDlistendCount = %i\n", sp->RFDlistendCount); + IPG_DDEBUG_MSG("RFDListCheckedCount = %i\n", sp->RFDListCheckedCount); + IPG_DDEBUG_MSG("EmptyRFDListCount = %i\n", sp->EmptyRFDListCount); + IPG_DUMPTFDLIST(ipg_ethernet_device); + + /* Reset all functions within the IPG to shut down the + IP1000* . + */ + i = IPG_AC_GLOBAL_RESET | IPG_AC_RX_RESET | + IPG_AC_TX_RESET | IPG_AC_DMA | + IPG_AC_FIFO | IPG_AC_NETWORK | + IPG_AC_HOST | IPG_AC_AUTO_INIT; + + error = ipg_reset(ipg_ethernet_device, i); + if (error < 0) + { + return error; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* Decrement the usage count for this IPG driver module. */ + MOD_DEC_USE_COUNT; +#endif + + /* Free all receive buffers. */ + for(i=0; iipg_pci_device, + sp->RxBuffDMAhandle[i].dmahandle, + sp->RxBuffDMAhandle[i].len, + PCI_DMA_FROMDEVICE); +#endif + if (sp->RxBuff[i] != NULL) + IPG_DEV_KFREE_SKB(sp->RxBuff[i]); + sp->RxBuff[i] = NULL; + } + + /* Free all transmit buffers. */ + for(i=0; iTxBuff[i] != NULL) + IPG_DEV_KFREE_SKB(sp->TxBuff[i]); + sp->TxBuff[i] = NULL; + } + +#ifdef IPG_LINUX2_2 + ipg_ethernet_device->start = 0; + set_bit(0,(void*)&ipg_ethernet_device->tbusy); + + /* Free memory associated with the RFDList. */ + kfree(sp->RFDList); + + /* Free memory associated with the TFDList. */ + kfree(sp->TFDList); +#endif + +#ifdef IPG_LINUX2_4 + netif_stop_queue(ipg_ethernet_device); + + /* Free memory associated with the RFDList. */ + pci_free_consistent(sp->ipg_pci_device, + (sizeof(struct RFD) * + IPG_RFDLIST_LENGTH), + sp->RFDList, sp->RFDListDMAhandle); + + /* Free memory associated with the TFDList. */ + pci_free_consistent(sp->ipg_pci_device, + (sizeof(struct TFD) * + IPG_TFDLIST_LENGTH), + sp->TFDList, sp->TFDListDMAhandle); +#endif + + /* Release interrupt line. */ + free_irq(ipg_ethernet_device->irq, ipg_ethernet_device); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return 0; +#endif + +#ifdef USE_IO_OPS + + /* Release I/O range reserved for IPG registers. */ + release_region(ipg_ethernet_device->base_addr, + IPG_IO_REG_RANGE); + +#else /* Not using I/O space. */ + + /* Unmap memory used for IPG registers. */ + + /* The following line produces strange results unless + * unregister_netdev precedes it. + */ + iounmap((void *)ipg_ethernet_device->base_addr); + +#endif + + return 0; +} + +int ipg_nic_hard_start_xmit(struct sk_buff *skb, + IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Transmit an Ethernet frame. */ + + u64 fraglen; + u64 vlanvid; + u64 vlancfi; + u64 vlanuserpriority; + unsigned long flags; + int NextTFD; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DDEBUG_MSG("_nic_hard_start_xmit\n"); + + baseaddr = ipg_ethernet_device->base_addr; + +#ifdef IPG_LINUX2_2 + /* If IPG NIC is already busy, return error. */ + if (test_and_set_bit(0, (void*)&ipg_ethernet_device->tbusy) != 0) + { + IPG_DEBUG_MSG("Transmit busy!\n"); + + return -EBUSY; + } +#endif + + /* Disable interrupts. */ + spin_lock_irqsave(&sp->lock, flags); + +#ifdef IPG_LINUX2_4 + /* If in 10Mbps mode, stop the transmit queue so + * no more transmit frames are accepted. + */ + if (sp->tenmbpsmode) + { + netif_stop_queue(ipg_ethernet_device); + } +#endif + + /* Next TFD is found by incrementing the CurrentTFD + * counter, modulus the length of the TFDList. + */ + NextTFD = (sp->CurrentTFD + 1) % IPG_TFDLIST_LENGTH; + + /* Check for availability of next TFD. */ + if (!(le64_to_cpu(sp->TFDList[NextTFD].TFC) & + IPG_TFC_TFDDONE) || (NextTFD == sp->LastFreedTxBuff)) + { + IPG_DEBUG_MSG("Next TFD not available.\n"); + + /* Attempt to free any used TFDs. */ + ipg_nic_txfree(ipg_ethernet_device); + +#ifdef IPG_LINUX2_2 + /* Transmit no longer busy. */ + clear_bit(0,(void*)&ipg_ethernet_device->tbusy); +#endif + + /* Restore interrupts. */ + spin_unlock_irqrestore(&sp->lock, flags); + +#ifdef IPG_DEBUG + /* Increment the TFDunavailCount counter. */ + sp->TFDunavailCount++; +#endif + + return -ENOMEM; + } + +#ifdef IPG_LINUX2_4 + sp->TxBuffDMAhandle[NextTFD].len = skb->len; + sp->TxBuffDMAhandle[NextTFD].dmahandle = pci_map_single( + sp->ipg_pci_device, + skb->data, skb->len, + PCI_DMA_TODEVICE); +#endif + + /* Save the sk_buff pointer so interrupt handler can later free + * memory occupied by buffer. + */ + sp->TxBuff[NextTFD] = skb; + + /* Clear all TFC fields, except TFDDONE. */ + sp->TFDList[NextTFD].TFC = cpu_to_le64(IPG_TFC_TFDDONE); + + /* Specify the TFC field within the TFD. */ + sp->TFDList[NextTFD]. + TFC |= cpu_to_le64(IPG_TFC_WORDALIGNDISABLED | + (IPG_TFC_FRAMEID & + cpu_to_le64(sp->CurrentTxFrameID)) | + (IPG_TFC_FRAGCOUNT & (1 << 24))); + + /* Request TxComplete interrupts at an interval defined + * by the constant IPG_FRAMESBETWEENTXCOMPLETES. + * Request TxComplete interrupt for every frame + * if in 10Mbps mode to accomodate problem with 10Mbps + * processing. + */ + if (sp->tenmbpsmode) + { + sp->TFDList[NextTFD].TFC |= + cpu_to_le64(IPG_TFC_TXINDICATE); + } + else if ((sp->CurrentTxFrameID % + IPG_FRAMESBETWEENTXDMACOMPLETES) == 0) + { + sp->TFDList[NextTFD].TFC |= + cpu_to_le64(IPG_TFC_TXDMAINDICATE); + } + + /* Based on compilation option, determine if FCS is to be + * appended to transmit frame by IPG. + */ + if (!(IPG_APPEND_FCS_ON_TX)) + { + sp->TFDList[NextTFD]. + TFC |= cpu_to_le64(IPG_TFC_FCSAPPENDDISABLE); + } + + /* Based on compilation option, determine if IP, TCP and/or + * UDP checksums are to be added to transmit frame by IPG. + */ + if (IPG_ADD_IPCHECKSUM_ON_TX) + { + sp->TFDList[NextTFD]. + TFC |= cpu_to_le64(IPG_TFC_IPCHECKSUMENABLE); + } + if (IPG_ADD_TCPCHECKSUM_ON_TX) + { + sp->TFDList[NextTFD]. + TFC |= cpu_to_le64(IPG_TFC_TCPCHECKSUMENABLE); + } + if (IPG_ADD_UDPCHECKSUM_ON_TX) + { + sp->TFDList[NextTFD]. + TFC |= cpu_to_le64(IPG_TFC_UDPCHECKSUMENABLE); + } + + /* Based on compilation option, determine if VLAN tag info is to be + * inserted into transmit frame by IPG. + */ + if (IPG_INSERT_MANUAL_VLAN_TAG) + { + vlanvid = IPG_MANUAL_VLAN_VID; + vlancfi = IPG_MANUAL_VLAN_CFI; + vlanuserpriority = IPG_MANUAL_VLAN_USERPRIORITY; + + sp->TFDList[NextTFD].TFC |= cpu_to_le64( + IPG_TFC_VLANTAGINSERT | + (vlanvid << 32) | + (vlancfi << 44) | + (vlanuserpriority << 45)); + } + + /* The fragment start location within system memory is defined + * by the sk_buff structure's data field. The physical address + * of this location within the system's virtual memory space + * is determined using the IPG_HOST2BUS_MAP function. + */ +#ifdef IPG_LINUX2_2 + sp->TFDList[NextTFD].FragInfo = cpu_to_le64( + IPG_HOST2BUS_MAP(skb->data)); +#endif + +#ifdef IPG_LINUX2_4 + sp->TFDList[NextTFD].FragInfo = cpu_to_le64( + sp->TxBuffDMAhandle[NextTFD].dmahandle); +#endif + + /* The length of the fragment within system memory is defined by + * the sk_buff structure's len field. + */ + fraglen = (u16)skb->len; + sp->TFDList[NextTFD].FragInfo |= cpu_to_le64(IPG_TFI_FRAGLEN & + (fraglen << 48)); + + /* Clear the TFDDone bit last to indicate the TFD is ready + * for transfer to the IPG. + */ + sp->TFDList[NextTFD].TFC &= cpu_to_le64(~IPG_TFC_TFDDONE); + + /* Record frame transmit start time (jiffies = Linux + * kernel current time stamp). + */ + ipg_ethernet_device->trans_start = jiffies; + + /* Update current TFD indicator. */ + sp->CurrentTFD = NextTFD; + + /* Calculate the new ID for the next transmit frame by + * incrementing the CurrentTxFrameID counter. + */ + sp->CurrentTxFrameID++; + + /* Force a transmit DMA poll event. */ + IPG_WRITE_DMACTRL(baseaddr, IPG_DC_TX_DMA_POLL_NOW); + + /* Restore interrupts. */ + spin_unlock_irqrestore(&sp->lock, flags); + +#ifdef IPG_LINUX2_2 + /* Transmit no longer busy. + * If in 10Mbps mode, do not indicate transmit is free + * until receive TxComplete interrupt. + */ + if (!(sp->tenmbpsmode)) + { + clear_bit(0,(void*)&ipg_ethernet_device->tbusy); + } +#endif + + return 0; +} + +#ifdef JUMBO_FRAME + +/* use jumboindex and jumbosize to control jumbo frame status + initial status is jumboindex=-1 and jumbosize=0 + 1. jumboindex = -1 and jumbosize=0 : previous jumbo frame has been done. + 2. jumboindex != -1 and jumbosize != 0 : jumbo frame is not over size and receiving + 3. jumboindex = -1 and jumbosize != 0 : jumbo frame is over size, already dump + previous receiving and need to continue dumping the current one +*/ +enum {NormalPacket,ErrorPacket}; +enum {Frame_NoStart_NoEnd=0,Frame_WithStart=1,Frame_WithEnd=10,Frame_WithStart_WithEnd=11}; +inline void ipg_nic_rx__FreeSkb(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + struct ipg_nic_private *sp = (struct ipg_nic_private *)ipg_ethernet_device->priv; + if (sp->RxBuff[sp->CurrentRFD] != NULL) + { +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device,sp->RxBuffDMAhandle[sp->CurrentRFD].dmahandle,sp->RxBuffDMAhandle[sp->CurrentRFD].len,PCI_DMA_FROMDEVICE); +#endif + IPG_DEV_KFREE_SKB(sp->RxBuff[sp->CurrentRFD]); + sp->RxBuff[sp->CurrentRFD] = NULL; + } +} +inline int ipg_nic_rx__CheckFrameSEType(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + struct ipg_nic_private *sp = (struct ipg_nic_private *)ipg_ethernet_device->priv; + int FoundStartEnd=0; + + if(le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS)&IPG_RFS_FRAMESTART)FoundStartEnd+=1; + if(le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS)&IPG_RFS_FRAMEEND)FoundStartEnd+=10; + return FoundStartEnd; //Frame_NoStart_NoEnd=0,Frame_WithStart=1,Frame_WithEnd=10,Frame_WithStart_WithEnd=11 +} +inline int ipg_nic_rx__CheckError(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + struct ipg_nic_private *sp = (struct ipg_nic_private *)ipg_ethernet_device->priv; + + if (IPG_DROP_ON_RX_ETH_ERRORS && + (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & + (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME | + IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR | + IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) + { + IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n", + (unsigned long int) sp->RFDList[sp->CurrentRFD].RFS); + + /* Increment general receive error statistic. */ + sp->stats.rx_errors++; + + /* Increment detailed receive error statistics. */ + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RXFIFOOVERRUN) + { + IPG_DEBUG_MSG("RX FIFO overrun occured.\n"); + + sp->stats.rx_fifo_errors++; + + if (sp->RxBuffNotReady == 1) + { + /* If experience a RxFIFO overrun, and + * the RxBuffNotReady flag is set, + * assume the FIFO overran due to lack + * of an RFD. + */ + sp->stats.rx_dropped++; + } + } + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RXRUNTFRAME) + { + IPG_DEBUG_MSG("RX runt occured.\n"); + sp->stats.rx_length_errors++; + } + + /* Do nothing for IPG_RFS_RXOVERSIZEDFRAME, + * error count handled by a IPG statistic register. + */ + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RXALIGNMENTERROR) + { + IPG_DEBUG_MSG("RX alignment error occured.\n"); + sp->stats.rx_frame_errors++; + } + + + /* Do nothing for IPG_RFS_RXFCSERROR, error count + * handled by a IPG statistic register. + */ + + /* Free the memory associated with the RX + * buffer since it is erroneous and we will + * not pass it to higher layer processes. + */ + if (sp->RxBuff[sp->CurrentRFD] != NULL) + { +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device, + sp->RxBuffDMAhandle[sp->CurrentRFD].dmahandle, + sp->RxBuffDMAhandle[sp->CurrentRFD].len, + PCI_DMA_FROMDEVICE); +#endif + + IPG_DEV_KFREE_SKB(sp->RxBuff[sp->CurrentRFD]); + sp->RxBuff[sp->CurrentRFD] = NULL; + } + return ErrorPacket; + } + return NormalPacket; +} +int ipg_nic_rx(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Transfer received Ethernet frames to higher network layers. */ + + int maxrfdcount; + int framelen; + int ThisEndFrameLen; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + struct sk_buff *skb; + + + IPG_DEBUG_MSG("_nic_rx\n"); + + baseaddr = ipg_ethernet_device->base_addr; + maxrfdcount = IPG_MAXRFDPROCESS_COUNT; + + while(le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RFDDONE) + { + if (--maxrfdcount == 0) + { + /* There are more RFDs to process, however the + * allocated amount of RFD processing time has + * expired. Assert Interrupt Requested to make + * sure we come back to process the remaining RFDs. + */ + IPG_WRITE_ASICCTRL(baseaddr, + IPG_READ_ASICCTRL(baseaddr) | + IPG_AC_INT_REQUEST); + break; + } + + switch(ipg_nic_rx__CheckFrameSEType(ipg_ethernet_device)) + { // Frame in one RFD +//----------- + case Frame_WithStart_WithEnd: + if(sp->Jumbo.FoundStart) + { + IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=NULL; + } + if(ipg_nic_rx__CheckError(ipg_ethernet_device)==NormalPacket)//1: found error, 0 no error + { // accept this frame and send to upper layer + skb = sp->RxBuff[sp->CurrentRFD]; + if(skb) + { + framelen=le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RXFRAMELEN; + if (framelen > IPG_RXFRAG_SIZE) framelen=IPG_RXFRAG_SIZE; + skb_put(skb, framelen); + /* Set the buffer's protocol field to Ehternet */ + skb->protocol=eth_type_trans(skb, ipg_ethernet_device); + /* Not handle TCP/UDP/IP checksum */ + skb->ip_summed=CHECKSUM_NONE; + netif_rx(skb); + ipg_ethernet_device->last_rx=jiffies; + sp->RxBuff[sp->CurrentRFD] = NULL; + } + }//if(ipg_nic_rx__CheckError(ipg_ethernet_device)==0)//1: found error, 0 no error + break;//case Frame_WithStart_WithEnd: +//----------- + case Frame_WithStart: + if(ipg_nic_rx__CheckError(ipg_ethernet_device)==NormalPacket)//1: found error, 0 no error + { // accept this frame and send to upper layer + skb = sp->RxBuff[sp->CurrentRFD]; + if(skb) + { + if(sp->Jumbo.FoundStart) + { + IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + } +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device, + sp->RxBuffDMAhandle[sp->CurrentRFD].dmahandle, + sp->RxBuffDMAhandle[sp->CurrentRFD].len, + PCI_DMA_FROMDEVICE); +#endif + sp->Jumbo.FoundStart=1; + sp->Jumbo.CurrentSize=IPG_RXFRAG_SIZE; + sp->Jumbo.skb=skb; + skb_put(sp->Jumbo.skb, IPG_RXFRAG_SIZE); + sp->RxBuff[sp->CurrentRFD] = NULL; + ipg_ethernet_device->last_rx=jiffies; + } + }//if(ipg_nic_rx__CheckError(ipg_ethernet_device)==0)//1: found error, 0 no error + break;//case Frame_WithStart: +//----------- + case Frame_WithEnd: + if(ipg_nic_rx__CheckError(ipg_ethernet_device)==NormalPacket)//1: found error, 0 no error + { // accept this frame and send to upper layer + skb = sp->RxBuff[sp->CurrentRFD]; + if(skb) + { + if(sp->Jumbo.FoundStart) + { + framelen=le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & IPG_RFS_RXFRAMELEN; + ThisEndFrameLen=framelen-sp->Jumbo.CurrentSize; + //if (framelen > IPG_RXFRAG_SIZE) framelen=IPG_RXFRAG_SIZE; + if(framelen>IPG_RXSUPPORT_SIZE) + { + IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + } + else + { + memcpy(skb_put(sp->Jumbo.skb,ThisEndFrameLen),skb->data,ThisEndFrameLen); + /* Set the buffer's protocol field to Ehternet */ + sp->Jumbo.skb->protocol=eth_type_trans(sp->Jumbo.skb, ipg_ethernet_device); + /* Not handle TCP/UDP/IP checksum */ + sp->Jumbo.skb->ip_summed=CHECKSUM_NONE; + netif_rx(sp->Jumbo.skb); + } + }//"if(sp->Jumbo.FoundStart)" + + ipg_ethernet_device->last_rx=jiffies; + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=NULL; + //Free this buffer(JC-ADVANCE) + ipg_nic_rx__FreeSkb(ipg_ethernet_device); + }//"if(skb)" + }//"if(ipg_nic_rx__CheckError(ipg_ethernet_device)==0)//1: found error, 0 no error" + else + { + IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=NULL; + } + break;//case Frame_WithEnd: +//----------- + case Frame_NoStart_NoEnd: + if(ipg_nic_rx__CheckError(ipg_ethernet_device)==NormalPacket)//1: found error, 0 no error + { // accept this frame and send to upper layer + skb = sp->RxBuff[sp->CurrentRFD]; + if(skb) + { + if(sp->Jumbo.FoundStart) + { + //if (framelen > IPG_RXFRAG_SIZE) framelen=IPG_RXFRAG_SIZE; + sp->Jumbo.CurrentSize+=IPG_RXFRAG_SIZE; + if(sp->Jumbo.CurrentSize>IPG_RXSUPPORT_SIZE) + { + /*IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=NULL;*/ + } + else + { + memcpy(skb_put(sp->Jumbo.skb,IPG_RXFRAG_SIZE),skb->data,IPG_RXFRAG_SIZE); + } + }//"if(sp->Jumbo.FoundStart)" + ipg_ethernet_device->last_rx=jiffies; + ipg_nic_rx__FreeSkb(ipg_ethernet_device); + } + }//if(ipg_nic_rx__CheckError(ipg_ethernet_device)==0)//1: found error, 0 no error + else + { + IPG_DEV_KFREE_SKB(sp->Jumbo.skb); + sp->Jumbo.FoundStart=0; + sp->Jumbo.CurrentSize=0; + sp->Jumbo.skb=NULL; + } + break;//case Frame_NoStart_NoEnd: + }//switch(ipg_nic_rx__CheckFrameSEType(ipg_ethernet_device)) + + sp->CurrentRFD = (sp->CurrentRFD+1) % IPG_RFDLIST_LENGTH; + } /* end of while(IPG_RFS_RFDDONE)*/ + + ipg_nic_rxrestore(ipg_ethernet_device); + return 0; +} + + +#else +int ipg_nic_rx(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Transfer received Ethernet frames to higher network layers. */ + + int maxrfdcount; + int framelen; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + struct sk_buff *skb; + + IPG_DEBUG_MSG("_nic_rx\n"); + + baseaddr = ipg_ethernet_device->base_addr; + maxrfdcount = IPG_MAXRFDPROCESS_COUNT; + + while((le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS)) & + IPG_RFS_RFDDONE && + (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS)) & + IPG_RFS_FRAMESTART && + (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS)) & + IPG_RFS_FRAMEEND && + (sp->RxBuff[sp->CurrentRFD] != NULL)) + { + if (--maxrfdcount == 0) + { + /* There are more RFDs to process, however the + * allocated amount of RFD processing time has + * expired. Assert Interrupt Requested to make + * sure we come back to process the remaining RFDs. + */ + IPG_WRITE_ASICCTRL(baseaddr, + IPG_READ_ASICCTRL(baseaddr) | + IPG_AC_INT_REQUEST); + break; + } + + /* Get received frame length. */ + framelen = le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS) & + IPG_RFS_RXFRAMELEN; + + /* Check for jumbo frame arrival with too small + * RXFRAG_SIZE. + */ + if (framelen > IPG_RXFRAG_SIZE) + { + IPG_DEBUG_MSG("RFS FrameLen > allocated fragment size.\n"); + + framelen = IPG_RXFRAG_SIZE; + } + + /* Get the received frame buffer. */ + skb = sp->RxBuff[sp->CurrentRFD]; + + if ((IPG_DROP_ON_RX_ETH_ERRORS && + (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + (IPG_RFS_RXFIFOOVERRUN | + IPG_RFS_RXRUNTFRAME | + IPG_RFS_RXALIGNMENTERROR | + IPG_RFS_RXFCSERROR | + IPG_RFS_RXOVERSIZEDFRAME | + IPG_RFS_RXLENGTHERROR))))) + { + + IPG_DEBUG_MSG("Rx error, RFS = %16.16lx\n", (unsigned long int) sp->RFDList[sp->CurrentRFD].RFS); + + /* Increment general receive error statistic. */ + sp->stats.rx_errors++; + + /* Increment detailed receive error statistics. */ + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RXFIFOOVERRUN)) + { + IPG_DEBUG_MSG("RX FIFO overrun occured.\n"); + + sp->stats.rx_fifo_errors++; + + if (sp->RxBuffNotReady == 1) + { + /* If experience a RxFIFO overrun, and + * the RxBuffNotReady flag is set, + * assume the FIFO overran due to lack + * of an RFD. + */ + sp->stats.rx_dropped++; + } + } + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RXRUNTFRAME)) + { + IPG_DEBUG_MSG("RX runt occured.\n"); + sp->stats.rx_length_errors++; + } + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RXOVERSIZEDFRAME)); + /* Do nothing, error count handled by a IPG + * statistic register. + */ + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RXALIGNMENTERROR)) + { + IPG_DEBUG_MSG("RX alignment error occured.\n"); + sp->stats.rx_frame_errors++; + } + + + if (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RXFCSERROR)); + /* Do nothing, error count handled by a IPG + * statistic register. + */ + + /* Free the memory associated with the RX + * buffer since it is erroneous and we will + * not pass it to higher layer processes. + */ + if (sp->RxBuff[sp->CurrentRFD] != NULL) + { +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device, + sp->RxBuffDMAhandle[sp->CurrentRFD].dmahandle, + sp->RxBuffDMAhandle[sp->CurrentRFD].len, + PCI_DMA_FROMDEVICE); +#endif + + IPG_DEV_KFREE_SKB(sp->RxBuff[sp->CurrentRFD]); + } + + } + else + { + + /* Adjust the new buffer length to accomodate the size + * of the received frame. + */ + skb_put(skb, framelen); + + /* Set the buffer's protocol field to Ethernet. */ + skb->protocol = eth_type_trans(skb, + ipg_ethernet_device); + + /* If the frame contains an IP/TCP/UDP frame, + * determine if upper layer must check IP/TCP/UDP + * checksums. + * + * NOTE: DO NOT RELY ON THE TCP/UDP CHECKSUM + * VERIFICATION FOR SILICON REVISIONS B3 + * AND EARLIER! + * + if ((le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + (IPG_RFS_TCPDETECTED | + IPG_RFS_UDPDETECTED | + IPG_RFS_IPDETECTED))) && + !(le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + (IPG_RFS_TCPERROR | + IPG_RFS_UDPERROR | + IPG_RFS_IPERROR)))) + { + * Indicate IP checksums were performed + * by the IPG. + * + skb->ip_summed = CHECKSUM_UNNECESSARY; + } + else + */ + if (1==1) + { + /* The IPG encountered an error with (or + * there were no) IP/TCP/UDP checksums. + * This may or may not indicate an invalid + * IP/TCP/UDP frame was received. Let the + * upper layer decide. + */ + skb->ip_summed = CHECKSUM_NONE; + } + + /* Hand off frame for higher layer processing. + * The function netif_rx() releases the sk_buff + * when processing completes. + */ + netif_rx(skb); + + /* Record frame receive time (jiffies = Linux + * kernel current time stamp). + */ + ipg_ethernet_device->last_rx = jiffies; + } + + /* Assure RX buffer is not reused by IPG. */ + sp->RxBuff[sp->CurrentRFD] = NULL; + + /* Increment the current RFD counter. */ + sp->CurrentRFD = (sp->CurrentRFD + 1) % IPG_RFDLIST_LENGTH; + + } + + +#ifdef IPG_DEBUG + /* Check if the RFD list contained no receive frame data. */ + if (maxrfdcount == IPG_MAXRFDPROCESS_COUNT) + { + sp->EmptyRFDListCount++; + } +#endif + while((le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_RFDDONE)) && + !((le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_FRAMESTART)) && + (le64_to_cpu(sp->RFDList[sp->CurrentRFD].RFS & + IPG_RFS_FRAMEEND)))) + { + IPG_DEBUG_MSG("Frame requires multiple RFDs.\n"); + + /* An unexpected event, additional code needed to handle + * properly. So for the time being, just disregard the + * frame. + */ + + /* Free the memory associated with the RX + * buffer since it is erroneous and we will + * not pass it to higher layer processes. + */ + if (sp->RxBuff[sp->CurrentRFD] != NULL) + { +#ifdef IPG_LINUX2_4 + pci_unmap_single(sp->ipg_pci_device, + sp->RxBuffDMAhandle[sp->CurrentRFD].dmahandle, + sp->RxBuffDMAhandle[sp->CurrentRFD].len, + PCI_DMA_FROMDEVICE); +#endif + IPG_DEV_KFREE_SKB(sp->RxBuff[sp->CurrentRFD]); + } + + /* Assure RX buffer is not reused by IPG. */ + sp->RxBuff[sp->CurrentRFD] = NULL; + + /* Increment the current RFD counter. */ + sp->CurrentRFD = (sp->CurrentRFD + 1) % IPG_RFDLIST_LENGTH; + } + + /* Check to see if there are a minimum number of used + * RFDs before restoring any (should improve performance.) + */ + if (((sp->CurrentRFD > sp->LastRestoredRxBuff) && + ((sp->LastRestoredRxBuff + IPG_MINUSEDRFDSTOFREE) <= + sp->CurrentRFD)) || + ((sp->CurrentRFD < sp->LastRestoredRxBuff) && + ((sp->LastRestoredRxBuff + IPG_MINUSEDRFDSTOFREE) <= + (sp->CurrentRFD + IPG_RFDLIST_LENGTH)))) + { + ipg_nic_rxrestore(ipg_ethernet_device); + } + + return 0; +} +#endif +int ipg_nic_rxrestore(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Restore used receive buffers. */ + + int i; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_rxrestore\n"); + + /* Assume receive buffers will be available. */ + sp->RxBuffNotReady = 0; + + while (sp->RxBuff[i = ((sp->LastRestoredRxBuff + 1) % + IPG_RFDLIST_LENGTH)] == NULL) + { + /* Generate a new receive buffer to replace the + * current buffer (which will be released by the + * Linux system). + */ + if (ipg_get_rxbuff(ipg_ethernet_device, i) < 0) + { + IPG_DEBUG_MSG("Cannot allocate new Rx buffer.\n"); + + /* Mark a flag indicating a receive buffer + * was not available. Use this flag to update + * the rx_dropped Linux statistic. + */ + sp->RxBuffNotReady = 1; + + break; + } + + /* Reset the RFS field. */ + sp->RFDList[i].RFS = 0x0000000000000000; + + sp->LastRestoredRxBuff = i; + } + + return 0; +} + +IPG_STATS_TYPE* ipg_nic_get_stats(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Provides statistical information about the IPG NIC. */ + + u16 temp1; + u16 temp2; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_get_stats\n"); + + /* Check to see if the NIC has been initialized via nic_open, + * before trying to read statistic registers. + */ +#ifdef IPG_LINUX2_2 + if (ipg_ethernet_device->start == 0) + { +#endif +#ifdef IPG_LINUX2_4 + if (!test_bit(__LINK_STATE_START, &ipg_ethernet_device->state)) + { +#endif + return &sp->stats; + } + + + baseaddr = ipg_ethernet_device->base_addr; + + sp->stats.rx_packets += IPG_READ_FRAMESRCVDOK(baseaddr); + sp->stats.tx_packets += IPG_READ_FRAMESXMTDOK(baseaddr); + sp->stats.rx_bytes += IPG_READ_OCTETRCVOK(baseaddr); + sp->stats.tx_bytes += IPG_READ_OCTETXMTOK(baseaddr); + temp1 = IPG_READ_FRAMESLOSTRXERRORS(baseaddr); + sp->stats.rx_errors += temp1; + sp->stats.rx_missed_errors += temp1; + temp1 = IPG_READ_SINGLECOLFRAMES(baseaddr) + + IPG_READ_MULTICOLFRAMES(baseaddr) + + IPG_READ_LATECOLLISIONS(baseaddr); + temp2 = IPG_READ_CARRIERSENSEERRORS(baseaddr); + sp->stats.collisions += temp1; + sp->stats.tx_dropped += IPG_READ_FRAMESABORTXSCOLLS(baseaddr); + sp->stats.tx_errors += IPG_READ_FRAMESWEXDEFERRAL(baseaddr) + + IPG_READ_FRAMESWDEFERREDXMT(baseaddr) + + temp1 + temp2; + sp->stats.multicast += IPG_READ_MCSTOCTETRCVDOK(baseaddr); + + /* detailed tx_errors */ + sp->stats.tx_carrier_errors += temp2; + + /* detailed rx_errors */ + sp->stats.rx_length_errors += IPG_READ_INRANGELENGTHERRORS(baseaddr) + + IPG_READ_FRAMETOOLONGERRRORS(baseaddr); + sp->stats.rx_crc_errors += IPG_READ_FRAMECHECKSEQERRORS(baseaddr); + + /* Unutilized IPG statistic registers. */ + IPG_READ_MCSTFRAMESRCVDOK(baseaddr); + + /* Masked IPG statistic registers (need not be read to clear) + IPG_READ_MACCONTROLFRAMESXMTDOK(baseaddr); + IPG_READ_BCSTFRAMESXMTDOK(baseaddr); + IPG_READ_MCSTFRAMESXMTDOK(baseaddr); + IPG_READ_BCSTOCTETXMTOK(baseaddr); + IPG_READ_MCSTOCTETXMTOK(baseaddr); + IPG_READ_MACCONTROLFRAMESRCVD(baseaddr); + IPG_READ_BCSTFRAMESRCVDOK(baseaddr); + IPG_READ_BCSTOCTETRCVOK(baseaddr); + IPG_READ_TXJUMBOFRAMES(baseaddr); + IPG_READ_UDPCHECKSUMERRORS(baseaddr); + IPG_READ_IPCHECKSUMERRORS(baseaddr); + IPG_READ_TCPCHECKSUMERRORS(baseaddr); + IPG_READ_RXJUMBOFRAMES(baseaddr); + */ + + + /* Unutilized RMON statistic registers. */ + + /* Masked IPG statistic registers (need not be read to clear) + IPG_READ_ETHERSTATSCOLLISIONS(baseaddr); + IPG_READ_ETHERSTATSOCTETSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS64OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT(baseaddr); + IPG_READ_ETHERSTATSCRCALIGNERRORS(baseaddr); + IPG_READ_ETHERSTATSUNDERSIZEPKTS(baseaddr); + IPG_READ_ETHERSTATSFRAGMENTS(baseaddr); + IPG_READ_ETHERSTATSJABBERS(baseaddr); + IPG_READ_ETHERSTATSOCTETS(baseaddr); + IPG_READ_ETHERSTATSPKTS(baseaddr); + IPG_READ_ETHERSTATSPKTS64OCTESTS(baseaddr); + IPG_READ_ETHERSTATSPKTS65TO127OCTESTS(baseaddr); + IPG_READ_ETHERSTATSPKTS128TO255OCTESTS(baseaddr); + IPG_READ_ETHERSTATSPKTS256TO511OCTESTS(baseaddr); + IPG_READ_ETHERSTATSPKTS512TO1023OCTESTS(baseaddr); + IPG_READ_ETHERSTATSPKTS1024TO1518OCTESTS(baseaddr); + */ + + return &sp->stats; +} + +void ipg_nic_set_multicast_list(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Determine and configure multicast operation and set + * receive mode for IPG. + */ + u8 receivemode; + u32 hashtable[2]; + unsigned int hashindex; + u32 baseaddr; + struct dev_mc_list *mc_list_ptr; + + + IPG_DEBUG_MSG("_nic_set_multicast_list\n"); + + baseaddr = ipg_ethernet_device->base_addr; + + receivemode = IPG_RM_RECEIVEUNICAST | + IPG_RM_RECEIVEBROADCAST; + + if (ipg_ethernet_device->flags & IFF_PROMISC) + { + /* NIC to be configured in promiscuous mode. */ + receivemode = IPG_RM_RECEIVEALLFRAMES; + } + else if ((ipg_ethernet_device->flags & IFF_ALLMULTI) || + (ipg_ethernet_device->flags & IFF_MULTICAST & + (ipg_ethernet_device->mc_count > + IPG_MULTICAST_HASHTABLE_SIZE))) + { + /* NIC to be configured to receive all multicast + * frames. */ + receivemode |= IPG_RM_RECEIVEMULTICAST; + } + else if (ipg_ethernet_device->flags & IFF_MULTICAST & + (ipg_ethernet_device->mc_count > 0)) + { + /* NIC to be configured to receive selected + * multicast addresses. */ + receivemode |= IPG_RM_RECEIVEMULTICASTHASH; + } + + /* Calculate the bits to set for the 64 bit, IPG HASHTABLE. + * The IPG applies a cyclic-redundancy-check (the same CRC + * used to calculate the frame data FCS) to the destination + * address all incoming multicast frames whose destination + * address has the multicast bit set. The least significant + * 6 bits of the CRC result are used as an addressing index + * into the hash table. If the value of the bit addressed by + * this index is a 1, the frame is passed to the host system. + */ + + /* Clear hashtable. */ + hashtable[0] = 0x00000000; + hashtable[1] = 0x00000000; + + /* Cycle through all multicast addresses to filter.*/ + for (mc_list_ptr = ipg_ethernet_device->mc_list; + mc_list_ptr != NULL; + mc_list_ptr = mc_list_ptr->next) + { + /* Calculate CRC result for each multicast address. */ + hashindex = ether_crc_le(ETH_ALEN, mc_list_ptr->dmi_addr); + + /* Use only the least significant 6 bits. */ + hashindex = hashindex & 0x3F; + + /* Within "hashtable", set bit number "hashindex" + * to a logic 1. + */ + set_bit(hashindex, (void*)hashtable); + } + + /* Write the value of the hashtable, to the 4, 16 bit + * HASHTABLE IPG registers. + */ + IPG_WRITE_HASHTABLE0(baseaddr, hashtable[0]); + IPG_WRITE_HASHTABLE1(baseaddr, hashtable[1]); + + IPG_WRITE_RECEIVEMODE(baseaddr, receivemode); + + IPG_DEBUG_MSG("ReceiveMode = %x\n",IPG_READ_RECEIVEMODE(baseaddr)); + + return; +} + +/* + * The following code fragment was authored by Donald Becker. + */ + +/* The little-endian AUTODIN II ethernet CRC calculations. + A big-endian version is also available. + This is slow but compact code. Do not use this routine for bulk data, + use a table-based routine instead. + This is common code and should be moved to net/core/crc.c. + Chips may use the upper or lower CRC bits, and may reverse and/or invert + them. Select the endian-ness that results in minimal calculations. +*/ +unsigned const ethernet_polynomial_le = 0xedb88320U; +unsigned ether_crc_le(int length, unsigned char *data) +{ + unsigned int crc = 0xffffffff; /* Initial value. */ + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 8; --bit >= 0; current_octet >>= 1) { + if ((crc ^ current_octet) & 1) { + crc >>= 1; + crc ^= ethernet_polynomial_le; + } else + crc >>= 1; + } + } + return crc; +} +/* + * End of code fragment authored by Donald Becker. + */ + +int ipg_nic_init(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + /* Initialize IPG NIC. */ + + struct ipg_nic_private *sp = NULL; + + IPG_DEBUG_MSG("_nic_init\n"); + + /* Register the IPG NIC in the list of Ethernet devices. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + ipg_ethernet_device = init_etherdev(ipg_ethernet_device, + sizeof(struct ipg_nic_private)); +#else + ipg_ethernet_device=alloc_etherdev(sizeof(struct ipg_nic_private)); +#endif + + if (ipg_ethernet_device == NULL) + { + printk(KERN_INFO "Could not initialize IP1000 based NIC.\n"); + return -ENODEV; + } + + /* Reserve memory for ipg_nic_private structure. */ + sp = kmalloc(sizeof(struct ipg_nic_private), + GFP_KERNEL); + + if (sp == NULL) + { + printk(KERN_INFO "%s: No memory available for IP1000 private strucutre.\n", ipg_ethernet_device->name); + return -ENOMEM; + } + else + { + /* Fill the allocated memory space with 0s. + * Essentially sets all ipg_nic_private + * structure fields to 0. + */ + memset(sp, 0, sizeof(*sp)); + ipg_ethernet_device->priv = sp; + } + + /* Assign the new device to the list of IPG Ethernet devices. */ + sp->next_ipg_ethernet_device = root_ipg_ethernet_device; + root_ipg_ethernet_device = ipg_ethernet_device; + + /* Declare IPG NIC functions for Ethernet device methods. + */ + ipg_ethernet_device->open = &ipg_nic_open; + ipg_ethernet_device->stop = &ipg_nic_stop; + ipg_ethernet_device->hard_start_xmit = &ipg_nic_hard_start_xmit; + ipg_ethernet_device->get_stats = &ipg_nic_get_stats; + ipg_ethernet_device->set_multicast_list = + &ipg_nic_set_multicast_list; + ipg_ethernet_device->do_ioctl = & ipg_nic_do_ioctl; + /* rebuild_header not defined. */ + /* hard_header not defined. */ + /* set_config not defined */ + /* set_mac_address not defined. */ + /* header_cache_bind not defined. */ + /* header_cache_update not defined. */ + ipg_ethernet_device->change_mtu = &ipg_nic_change_mtu; +#ifdef IPG_LINUX2_4 + /* ipg_ethernet_device->tx_timouet not defined. */ + /* ipg_ethernet_device->watchdog_timeo not defined. */ +#endif + + return 0; +} + +int ipg_nic_do_ioctl(IPG_DEVICE_TYPE *ipg_ethernet_device, + struct ifreq *req, int cmd) +{ + /* IOCTL commands for IPG NIC. + * + * SIOCDEVPRIVATE nothing + * SIOCDEVPRIVATE+1 register read + * ifr_data[0] = 0x08, 0x10, 0x20 + * ifr_data[1] = register offset + * ifr_data[2] = value read + * SIOCDEVPRIVATE+2 register write + * ifr_data[0] = 0x08, 0x10, 0x20 + * ifr_data[1] = register offset + * ifr_data[2] = value to write + * SIOCDEVPRIVATE+3 GMII register read + * ifr_data[1] = register offset + * SIOCDEVPRIVATE+4 GMII register write + * ifr_data[1] = register offset + * ifr_data[2] = value to write + * SIOCDEVPRIVATE+5 PCI register read + * ifr_data[0] = 0x08, 0x10, 0x20 + * ifr_data[1] = register offset + * ifr_data[2] = value read + * SIOCDEVPRIVATE+6 PCI register write + * ifr_data[0] = 0x08, 0x10, 0x20 + * ifr_data[1] = register offset + * ifr_data[2] = value to write + * + */ + + u8 val8; + u16 val16; + u32 val32; + unsigned int *data; + int phyaddr = 0; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + + IPG_DEBUG_MSG("_nic_do_ioctl\n"); + + data = (unsigned int *)&req->ifr_data; + baseaddr = ipg_ethernet_device->base_addr; + + switch(cmd) + { + case SIOCDEVPRIVATE: + return 0; + + case SIOCDEVPRIVATE+1: + switch(data[0]) + { + case 0x08: + data[2] = IPG_READ_BYTEREG(baseaddr + data[1]); + return 0; + + case 0x10: + data[2] = IPG_READ_WORDREG(baseaddr + data[1]); + return 0; + + case 0x20: + data[2] = IPG_READ_LONGREG(baseaddr + data[1]); + return 0; + + default: + data[2] = 0x00; + return -EINVAL; + } + + case SIOCDEVPRIVATE+2: + switch(data[0]) + { + case 0x08: + IPG_WRITE_BYTEREG(baseaddr + data[1], data[2]); + return 0; + + case 0x10: + IPG_WRITE_WORDREG(baseaddr + data[1], data[2]); + return 0; + + case 0x20: + IPG_WRITE_LONGREG(baseaddr + data[1], data[2]); + return 0; + + default: + return -EINVAL; + } + + case SIOCDEVPRIVATE+3: + phyaddr = ipg_find_phyaddr(ipg_ethernet_device); + + if (phyaddr == -1) + return -EINVAL; + + data[2] = read_phy_register(ipg_ethernet_device, + phyaddr, data[1]); + + return 0; + + case SIOCDEVPRIVATE+4: + phyaddr = ipg_find_phyaddr(ipg_ethernet_device); + + if (phyaddr == -1) + return -EINVAL; + + write_phy_register(ipg_ethernet_device, + phyaddr, data[1], (u16)data[2]); + + return 0; + + case SIOCDEVPRIVATE+5: + switch(data[0]) + { + case 0x08: + pci_read_config_byte(sp->ipg_pci_device,data[1], + &val8); + data[2] = (unsigned int)val8; + return 0; + + case 0x10: + pci_read_config_word(sp->ipg_pci_device,data[1], + &val16); + data[2] = (unsigned int)val16; + return 0; + + case 0x20: + pci_read_config_dword(sp->ipg_pci_device,data[1], + &val32); + data[2] = (unsigned int)val32; + return 0; + + default: + data[2] = 0x00; + return -EINVAL; + } + + case SIOCDEVPRIVATE+6: + switch(data[0]) + { + case 0x08: + pci_write_config_byte(sp->ipg_pci_device,data[1], + (u8)data[2]); + return 0; + + case 0x10: + pci_write_config_word(sp->ipg_pci_device,data[1], + (u16)data[2]); + return 0; + + case 0x20: + pci_write_config_dword(sp->ipg_pci_device,data[1], + (u32)data[2]); + return 0; + + default: + return -EINVAL; + } + + case SIOCSIFMTU: + { + return 0; + } + + default: + return -EOPNOTSUPP; + } +} + +int ipg_nic_change_mtu(IPG_DEVICE_TYPE *ipg_ethernet_device, + int new_mtu) +{ + /* Function to accomodate changes to Maximum Transfer Unit + * (or MTU) of IPG NIC. Cannot use default function since + * the default will not allow for MTU > 1500 bytes. + */ + + IPG_DEBUG_MSG("_nic_change_mtu\n"); + + /* Check that the new MTU value is between 68 (14 byte header, 46 + * byte payload, 4 byte FCS) and IPG_MAX_RXFRAME_SIZE, which + * corresponds to the MAXFRAMESIZE register in the IPG. + */ + if ((new_mtu < 68) || (new_mtu > IPG_MAX_RXFRAME_SIZE)) + { + return -EINVAL; + } + + ipg_ethernet_device->mtu = new_mtu; + + return 0; +} + +#ifdef IPG_LINUX2_2 +int ipg_pcibussearch_linux2_2(void) +{ + /* Search for IPG based devices on the Ethernet bus. + * Code specific to the Linux 2.2 kernel. + */ + + int error; + int i; + int foundipgnic = 0; + IPG_DEVICE_TYPE *ipg_ethernet_device; + struct ipg_nic_private *sp; + struct pci_dev *ipg_pci_device; + + IPG_DEBUG_MSG("_pcibussearch_linux_2_2\n"); + + for(i=0; ; i++) + { + if (nics_supported[i].vendorid == 0xFFFF) + break; + + /* Start with the list of all PCI devices. */ + ipg_pci_device = pci_devices; + + /* Check each entry in the list of all PCI devices. */ + while (ipg_pci_device) + { + if ((ipg_pci_device->vendor == + nics_supported[i].vendorid) && + (ipg_pci_device->device == + nics_supported[i].deviceid)) + { + foundipgnic = 1; + + printk(KERN_INFO "%s found.\n", + nics_supported[i].NICname); + printk(KERN_INFO "Bus %x Slot %x\n", + ipg_pci_device->bus->number, + PCI_SLOT(ipg_pci_device->devfn)); + + ipg_ethernet_device = NULL; + + /* A IPG based NIC was found on the PCI bus. + * Initialize the NIC. + */ + error = ipg_nic_init(ipg_ethernet_device); + if (error < 0) + { + printk(KERN_INFO "Could not intialize IP1000 based NIC.\n"); + return error; + } + else + { + printk(KERN_INFO "Ethernet device registered as: %s\n", + root_ipg_ethernet_device->name); + } + + sp = (struct ipg_nic_private *) + root_ipg_ethernet_device->priv; + + /* Save the pointer to the PCI device + * information. + */ + sp->ipg_pci_device = ipg_pci_device; + } + + /* Move onto the next PCI device in the list. */ + ipg_pci_device = ipg_pci_device->next; + } + + } + + return foundipgnic; +} +#endif + +#ifdef IPG_LINUX2_4 + +/* PCI driver structure for Linux 2.4. */ +struct pci_driver ipg_pci_driver = +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + name: IPG_DRIVER_NAME, + id_table: pci_devices_supported, + probe: ipg_pciprobe_linux2_4, + remove: ipg_pciremove_linux2_4, +#else + {NULL, NULL}, + IPG_DRIVER_NAME, + pci_devices_supported, + ipg_pciprobe_linux2_4, + ipg_pciremove_linux2_4, + NULL, + NULL +#endif +}; + +void ipg_pciremove_linux2_4(struct pci_dev *ipg_pci_device_to_remove) +{ + /* Remove function called when a IPG device is + * to be shut down. + */ + + IPG_DEVICE_TYPE *prev_ipg_ethernet_device = NULL; + IPG_DEVICE_TYPE *ipg_ethernet_device = NULL; + IPG_DEVICE_TYPE *ipg_ethernet_device_to_remove = + NULL; + struct ipg_nic_private *prev_sp = NULL; + struct ipg_nic_private *sp = NULL; + struct ipg_nic_private *sp_to_remove = NULL; + + IPG_DEBUG_MSG("_pciremove_linux2_4\n"); + + ipg_ethernet_device = root_ipg_ethernet_device; + + /* Move through list of Ethernet devices looking for + * a match. + */ + while (ipg_ethernet_device) + { + sp = (struct ipg_nic_private *) + (ipg_ethernet_device->priv); + + if (sp->ipg_pci_device == ipg_pci_device_to_remove) + { + /* Save the pointer to the previous Ethernet + * device. + */ + ipg_ethernet_device_to_remove = + ipg_ethernet_device; + + sp_to_remove = sp; + + break; + } + + /* Save the "previous" device in the list. */ + prev_ipg_ethernet_device = ipg_ethernet_device; + + /* Retrieve next Ethernet device to be + * released. + */ + ipg_ethernet_device = sp->next_ipg_ethernet_device; + } + + /* Check if there is a device to remove. */ + if (ipg_ethernet_device_to_remove == NULL) + { + /* There are no Ethernet devices to remove. */ + printk(KERN_INFO "A device remove request does not match with any Ethernet devices.\n"); + + return; + } + + /* Check to see if we are removing the root device in the list. */ + if (root_ipg_ethernet_device == ipg_ethernet_device_to_remove) + { + /* Change the root Ethernet device to the next device to be + * released. + */ + root_ipg_ethernet_device = + sp_to_remove->next_ipg_ethernet_device; + } + else if (sp_to_remove->next_ipg_ethernet_device != NULL) + /* Check if we need to re-link the list of devices. */ + { + /* If the "previous" Ethernet device is NULL, + * the device is at the head of the list, and + * no re-linking is needed. + */ + prev_sp = (struct ipg_nic_private *) + (prev_ipg_ethernet_device->priv); + + prev_sp->next_ipg_ethernet_device = + sp_to_remove->next_ipg_ethernet_device; + } + + /* Free memory associated with Ethernet device's + * private data structure. + */ + if (sp_to_remove) + { + kfree(sp_to_remove); + } + + printk(KERN_INFO "Un-registering Ethernet device %s\n", + ipg_ethernet_device_to_remove->name); + + /* Un-register Ethernet device. */ + unregister_netdev(ipg_ethernet_device_to_remove); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +#ifdef USE_IO_OPS + pci_release_regions(ipg_pci_device_to_remove); +#else + iounmap((void *)ipg_ethernet_device->base_addr); +#endif +#endif + + + /* Free memory associated with Ethernet device. */ + if (ipg_ethernet_device_to_remove) + { + kfree(ipg_ethernet_device_to_remove); + } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + pci_set_drvdata(ipg_pci_device_to_remove,NULL); +#endif + return; +} + +int ipg_pciprobe_linux2_4(struct pci_dev *ipg_pci_device, + const struct pci_device_id *id) +{ + /* Probe function called when a IPG device is found + * on the PCI bus. + */ + + int error; + int i; + IPG_DEVICE_TYPE *ipg_ethernet_device = NULL; + struct ipg_nic_private *sp; + + IPG_DEBUG_MSG("_pciprobe_linux2_4\n"); + + /* Enable IPG PCI device in Linux system. */ + error = pci_enable_device(ipg_pci_device); + if (error < 0) + { + return error; + } + + /* Get the index for the driver description string. */ + i = id->driver_data; + + printk(KERN_INFO "%s found.\n", + nics_supported[i].NICname); + printk(KERN_INFO "Bus %x Slot %x\n", + ipg_pci_device->bus->number, + PCI_SLOT(ipg_pci_device->devfn)); + + /* Configure IPG PCI device within Linux system as + * a bus master. + */ + pci_set_master(ipg_pci_device); + + /* Indicate that we can supply 32 bits of address + * during PCI bus mastering. + */ + if (pci_dma_supported(ipg_pci_device, 0xFFFFFFFF) < 0) + { + printk(KERN_INFO "pci_dma_supported failed.\n"); + return -ENODEV; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + /* A IPG based NIC was found on the PCI bus. + * Initialize the NIC. + */ + if ((ipg_nic_init(ipg_ethernet_device)) < 0) + { + printk(KERN_INFO "Could not intialize IP1000 based NIC.\n"); + return -ENODEV; + } + else + { + printk(KERN_INFO "Ethernet device registered as: %s\n", + root_ipg_ethernet_device->name); + } + sp = (struct ipg_nic_private *)root_ipg_ethernet_device->priv; + /* Save the pointer to the PCI device information. */ + sp->ipg_pci_device = ipg_pci_device; +#else + if ((ipg_nic_init(ipg_ethernet_device)) < 0) + { + printk(KERN_INFO "Could not intialize IP1000 based NIC.\n"); + return -ENODEV; + } + ipg_ethernet_device=root_ipg_ethernet_device; + SET_MODULE_OWNER(ipg_ethernet_device); + pci_request_regions(ipg_pci_device,DRV_NAME); +// if(pci_request_regions(ipg_pci_device,DRV_NAME)=err) goto xxx; + +#ifdef USE_IO_OPS + ipg_ethernet_device->base_addr = pci_resource_start(ipg_pci_device, 0)&0xffffff80;////20040826Jesse_mask_BaseAddr:Mask IOBaseAddr[bit0~6] +#else + ipg_ethernet_device->base_addr = pci_resource_start(ipg_pci_device, 1)&0xffffff80;//20040826Jesse_mask_BaseAddr:Mask MemBaseAddr[bit0~6] + ipg_ethernet_device->base_addr = (long) ioremap (ipg_ethernet_device->base_addr, netdev_io_size); +// if (!ioaddr)goto err_out_res; +#endif//#ifdef USE_IO_OPS + sp = (struct ipg_nic_private *)root_ipg_ethernet_device->priv; + /* Save the pointer to the PCI device information. */ + sp->ipg_pci_device = ipg_pci_device; + + pci_set_drvdata(ipg_pci_device,ipg_ethernet_device); + + i = register_netdev(ipg_ethernet_device); +// if (i)goto err_out_unmap_rx; + + printk(KERN_INFO "Ethernet device registered as: %s\n", + ipg_ethernet_device->name); +#endif//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + + + return 0; +} +#endif //#ifdef IPG_LINUX2_4 + + + +#ifdef MODULE +/* A modularized driver, i.e. not part of mainstream Linux + * kernel distribution. + */ +int init_module(void) +{ + /* Initialize the IPG driver module. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int foundipgnic = 0; +#endif + + IPG_DEBUG_MSG("init_module\n"); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return pci_module_init(&ipg_pci_driver); +#else + + printk(KERN_INFO "%s", version); + + /* Define EXPORT_NO_SYMBOLS macro for specifying no + * symbols to be exported. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + EXPORT_NO_SYMBOLS; +#endif + + /* The CONFIG_PCI macro is defined for systems which + * have a PCI bus. If the macro is undefined, there is no + * PCI bus and the ipg cannot be utilized. + */ +#ifdef CONFIG_PCI + + printk(KERN_INFO "IPG module searching for Ethernet devices on PCI bus...\n"); + +#ifdef IPG_LINUX2_2 + foundipgnic = ipg_pcibussearch_linux2_2(); +#endif + +#ifdef IPG_LINUX2_4 + if (pci_register_driver(&ipg_pci_driver) != 0) + { + foundipgnic = 1; + } + else + { + foundipgnic = 0; + } +#endif + + if (foundipgnic == 0) + { + printk(KERN_INFO " IP1000 based Ethernet device not found on PCI bus.\n"); + return -ENODEV; + } + +#else /* PCI not available. */ + /* PCI not supported in system. */ + printk(KERN_INFO "No PCI bus, required by IP1000.\n"); + return -ENODEV; +#endif + + printk(KERN_INFO "IPG module loaded.\n"); + + return 0; +#endif +} + +void cleanup_module(void) +{ + /* Clean up system modifications made by IPG driver + * module. + */ + +#ifdef IPG_LINUX2_2 + + IPG_DEVICE_TYPE *next_ipg_ethernet_device; + struct ipg_nic_private *sp; + + IPG_DEBUG_MSG("cleanup_module\n"); + + /* Unregister all IPG NICs from the list of Ethernet + * devices. + */ + while (root_ipg_ethernet_device) + { + sp = (struct ipg_nic_private *) + (root_ipg_ethernet_device->priv); + + /* Retrieve next Ethernet device to be + * released. + */ + next_ipg_ethernet_device = sp->next_ipg_ethernet_device; + + printk(KERN_INFO "Un-registering Ethernet device %s\n", + root_ipg_ethernet_device->name); + + /* Un-register Ethernet device. */ + unregister_netdev(root_ipg_ethernet_device); + + /* Free memory associated with Ethernet device's + * private data structure. + */ + kfree(sp); + + /* Free memory associated with Ethernet device. */ + kfree(root_ipg_ethernet_device); + + /* Move to next Ethernet device. */ + root_ipg_ethernet_device = next_ipg_ethernet_device; + } + +#endif + +#ifdef IPG_LINUX2_4 + IPG_DEBUG_MSG("cleanup_module\n"); + + pci_unregister_driver(&ipg_pci_driver); +#endif + + printk(KERN_INFO "IPG module unloaded.\n"); +} +#else /* not MODULE */ + +int ipg_nic_probe(IPG_DEVICE_TYPE *dev) +{ + int error; + + IPG_DEBUG_MSG("_nic_probe\n"); + + error = ipg_nic_init(dev); + if (error < 0) + return -ENODEV; + printk(KERN_INFO "%s", version); + + return 0; +} + +#endif +void bSetPhyDefaultParam(unsigned char Rev, + IPG_DEVICE_TYPE *ipg_ethernet_device,int phy_address) +{ + unsigned short Length; + unsigned char Revision; + unsigned short *pPHYParam; + unsigned short address,value; + + pPHYParam = &DefaultPhyParam[0]; + Length = *pPHYParam & 0x00FF; + Revision = (unsigned char) ((*pPHYParam) >> 8); + pPHYParam++; + while(Length != 0) + { + if(Rev == Revision) + { + while(Length >1) + { + address=*pPHYParam; + value=*(pPHYParam+1); + pPHYParam+=2; + write_phy_register(ipg_ethernet_device,phy_address,address, value); + Length -= 4; + } + + break; + } + else // advanced to next revision + { + pPHYParam += Length/2; + Length = *pPHYParam & 0x00FF; + Revision = (unsigned char) ((*pPHYParam) >> 8); + pPHYParam++; + } + } + return; +} + +/*JES20040127EEPROM*/ +int read_eeprom(IPG_DEVICE_TYPE *ipg_ethernet_device, int eep_addr) +{ + u32 baseaddr; + int i = 1000; + baseaddr = ipg_ethernet_device->base_addr; + + IPG_WRITE_EEPROMCTRL(baseaddr, IPG_EC_EEPROM_READOPCODE | (eep_addr & 0xff)); + while (i-- > 0) { + mdelay(10); + if (!(IPG_READ_EEPROMCTRL(baseaddr)&IPG_EC_EEPROM_BUSY)) { + return IPG_READ_EEPROMDATA (baseaddr); + } + } + return 0; +} + +/* Write EEPROM JES20040127EEPROM */ +//void Eeprom_Write(unsigned int card_index, unsigned eep_addr, unsigned writedata) +void write_eeprom(IPG_DEVICE_TYPE *ipg_ethernet_device, unsigned int eep_addr, unsigned int writedata) +{ +/* + u32 baseaddr; + baseaddr = ipg_ethernet_device->base_addr; + IPG_WRITE_EEPROMDATA(baseaddr, writedata ); + while ( (IPG_READ_EEPROMCTRL(baseaddr) & IPG_EC_EEPROM_BUSY ) ) { + } + IPG_WRITE_EEPROMCTRL (baseaddr, 0xC0 ); + while ( (IPG_READ_EEPROMCTRL(baseaddr)&IPG_EC_EEPROM_BUSY) ) { + } + IPG_WRITE_EEPROMCTRL(baseaddr, IPG_EC_EEPROM_WRITEOPCODE | (eep_addr & 0xff) ); + while ( (IPG_READ_EEPROMCTRL(baseaddr)&IPG_EC_EEPROM_BUSY) ) { + } + + return;*/ +} + +/* Set LED_Mode JES20040127EEPROM */ +void Set_LED_Mode(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + u32 LED_Mode_Value; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + baseaddr = ipg_ethernet_device->base_addr; + + LED_Mode_Value=IPG_READ_ASICCTRL(baseaddr); + LED_Mode_Value &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE |IPG_AC_LED_SPEED); + + if((sp->LED_Mode & 0x03) > 1){ + /* Write Asic Control Bit 29 */ + LED_Mode_Value |=IPG_AC_LED_MODE_BIT_1; + } + if((sp->LED_Mode & 0x01) == 1){ + /* Write Asic Control Bit 14 */ + LED_Mode_Value |=IPG_AC_LED_MODE; + } + if((sp->LED_Mode & 0x08) == 8){ + /* Write Asic Control Bit 27 */ + LED_Mode_Value |=IPG_AC_LED_SPEED; + } + IPG_WRITE_ASICCTRL(baseaddr,LED_Mode_Value); + + return; +} + +/* Set PHYSet JES20040127EEPROM */ +void Set_PHYSet(IPG_DEVICE_TYPE *ipg_ethernet_device) +{ + int PHYSet_Value; + u32 baseaddr; + struct ipg_nic_private *sp = (struct ipg_nic_private *) + ipg_ethernet_device->priv; + baseaddr = ipg_ethernet_device->base_addr; + + PHYSet_Value=IPG_READ_PHYSET(baseaddr); + PHYSet_Value &= ~(IPG_PS_MEM_LENB9B | IPG_PS_MEM_LEN9 |IPG_PS_NON_COMPDET); + PHYSet_Value |= ((sp->LED_Mode & 0x70) >> 4); + IPG_WRITE_PHYSET(baseaddr,PHYSet_Value); + + return; +} +/* end ipg.c */ diff --git a/drivers/net/ip1000a/ipg_main.o b/drivers/net/ip1000a/ipg_main.o new file mode 100644 index 0000000000000000000000000000000000000000..aa0ec0acd9d5ad228285bc4a9a6e043492847648 GIT binary patch literal 21588 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 0 for auto FCS append on TX. */ +#define IPG_APPEND_FCS_ON_TX TRUE + +/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS strip on RX. */ +#define IPG_STRIP_FCS_ON_RX TRUE + +/* Assign IPG_DROP_ON_RX_ETH_ERRORS > 0 to drop RX frames with + * Ethernet errors. + */ +#define IPG_DROP_ON_RX_ETH_ERRORS TRUE + +/* Assign IPG_INSERT_MANUAL_VLAN_TAG > 0 to insert VLAN tags manually + * (via TFC). + */ +#define IPG_INSERT_MANUAL_VLAN_TAG FALSE + +/* Assign IPG_ADD_IPCHECKSUM_ON_TX > 0 for auto IP checksum on TX. */ +#define IPG_ADD_IPCHECKSUM_ON_TX FALSE + +/* Assign IPG_ADD_TCPCHECKSUM_ON_TX > 0 for auto TCP checksum on TX. + * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER. + */ +#define IPG_ADD_TCPCHECKSUM_ON_TX FALSE + +/* Assign IPG_ADD_UDPCHECKSUM_ON_TX > 0 for auto UDP checksum on TX. + * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER. + */ +#define IPG_ADD_UDPCHECKSUM_ON_TX FALSE + +/* If inserting VLAN tags manually, assign the IPG_MANUAL_VLAN_xx + * constants as desired. + */ +#define IPG_MANUAL_VLAN_VID 0xABC +#define IPG_MANUAL_VLAN_CFI 0x1 +#define IPG_MANUAL_VLAN_USERPRIORITY 0x5 + +#define IPG_IO_REG_RANGE 0xFF +#define IPG_MEM_REG_RANGE 0x154 +#define IPG_DRIVER_NAME "Sundance Technology IPG Triple-Speed Ethernet" +#define IPG_NIC_PHY_ADDRESS 0x01 +#define IPG_DMALIST_ALIGN_PAD 0x07 +#define IPG_MULTICAST_HASHTABLE_SIZE 0x40 + +/* Number of miliseconds to wait after issuing a software reset. + * 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation. + */ +#define IPG_AC_RESETWAIT 0x05 + +/* Number of IPG_AC_RESETWAIT timeperiods before declaring timeout. */ +#define IPG_AC_RESET_TIMEOUT 0x0A + +/* Minimum number of miliseconds used to toggle MDC clock during + * MII/GMII register access. + */ +#define IPG_PC_PHYCTRLWAIT 0x01 + +#define IPG_TFDLIST_LENGTH 0x100 + +/* Number of frames between TxDMAComplete interrupt. + * 0 < IPG_FRAMESBETWEENTXDMACOMPLETES <= IPG_TFDLIST_LENGTH + */ +#define IPG_FRAMESBETWEENTXDMACOMPLETES 0x1 + +#ifdef JUMBO_FRAME + +# ifdef JUMBO_FRAME_SIZE_2K +# define JUMBO_FRAME_SIZE 2048 +# define __IPG_RXFRAG_SIZE 2048 +# else +# ifdef JUMBO_FRAME_SIZE_3K +# define JUMBO_FRAME_SIZE 3072 +# define __IPG_RXFRAG_SIZE 3072 +# else +# ifdef JUMBO_FRAME_SIZE_4K +# define JUMBO_FRAME_SIZE 4096 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_5K +# define JUMBO_FRAME_SIZE 5120 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_6K +# define JUMBO_FRAME_SIZE 6144 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_7K +# define JUMBO_FRAME_SIZE 7168 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_8K +# define JUMBO_FRAME_SIZE 8192 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_9K +# define JUMBO_FRAME_SIZE 9216 +# define __IPG_RXFRAG_SIZE 4088 +# else +# ifdef JUMBO_FRAME_SIZE_10K +# define JUMBO_FRAME_SIZE 10240 +# define __IPG_RXFRAG_SIZE 4088 +# else +# define JUMBO_FRAME_SIZE 4096 +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + +/* Size of allocated received buffers. Nominally 0x0600. + * Define larger if expecting jumbo frames. + */ +#ifdef JUMBO_FRAME +//IPG_TXFRAG_SIZE must <= 0x2b00, or TX will crash +#define IPG_TXFRAG_SIZE JUMBO_FRAME_SIZE +#endif + + +/* Size of allocated received buffers. Nominally 0x0600. + * Define larger if expecting jumbo frames. + */ +#ifdef JUMBO_FRAME +//4088=4096-8 +#define IPG_RXFRAG_SIZE __IPG_RXFRAG_SIZE +#define IPG_RXSUPPORT_SIZE IPG_MAX_RXFRAME_SIZE +#else +#define IPG_RXFRAG_SIZE 0x0600 +#define IPG_RXSUPPORT_SIZE IPG_RXFRAG_SIZE +#endif + +/* IPG_MAX_RXFRAME_SIZE <= IPG_RXFRAG_SIZE */ +#ifdef JUMBO_FRAME +#define IPG_MAX_RXFRAME_SIZE JUMBO_FRAME_SIZE +#else +#define IPG_MAX_RXFRAME_SIZE 0x0600 +#endif + +#define IPG_RFDLIST_LENGTH 0x100 + +/* Maximum number of RFDs to process per interrupt. + * 1 < IPG_MAXRFDPROCESS_COUNT < IPG_RFDLIST_LENGTH + */ +#define IPG_MAXRFDPROCESS_COUNT 0x80 + +/* Minimum margin between last freed RFD, and current RFD. + * 1 < IPG_MINUSEDRFDSTOFREE < IPG_RFDLIST_LENGTH + */ +#define IPG_MINUSEDRFDSTOFREE 0x80 + +/* Specify priority threshhold for a RxDMAPriority interrupt. */ +#define IPG_PRIORITY_THRESH 0x07 + +/* Specify the number of receive frames transferred via DMA + * before a RX interrupt is issued. + */ +#define IPG_RXFRAME_COUNT 0x08 + +/* specify the jumbo frame maximum size + * per unit is 0x600 (the RxBuffer size that one RFD can carry) + */ +#define MAX_JUMBOSIZE 0x8 // max is 12K + +/* Specify the maximum amount of time (in 64ns increments) to wait + * before issuing a RX interrupt if number of frames received + * is less than IPG_RXFRAME_COUNT. + * + * Value Time + * ------------------- + * 0x3D09 ~1ms + * 0x061A ~100us + * 0x009C ~10us + * 0x000F ~1us + */ +#define IPG_RXDMAWAIT_TIME 0x009C + +/* Key register values loaded at driver start up. */ + +/* TXDMAPollPeriod is specified in 320ns increments. + * + * Value Time + * --------------------- + * 0x00-0x01 320ns + * 0x03 ~1us + * 0x1F ~10us + * 0xFF ~82us + */ +#define IPG_TXDMAPOLLPERIOD_VALUE 0x26 +#define IPG_TXSTARTTHRESH_VALUE 0x0FFF + +/* TxDMAUrgentThresh specifies the minimum amount of + * data in the transmit FIFO before asserting an + * urgent transmit DMA request. + * + * Value Min TxFIFO occupied space before urgent TX request + * --------------------------------------------------------------- + * 0x00-0x04 128 bytes (1024 bits) + * 0x27 1248 bytes (~10000 bits) + * 0x30 1536 bytes (12288 bits) + * 0xFF 8192 bytes (65535 bits) + */ +#define IPG_TXDMAURGENTTHRESH_VALUE 0x04 + +/* TxDMABurstThresh specifies the minimum amount of + * free space in the transmit FIFO before asserting an + * transmit DMA request. + * + * Value Min TxFIFO free space before TX request + * ---------------------------------------------------- + * 0x00-0x08 256 bytes + * 0x30 1536 bytes + * 0xFF 8192 bytes + */ +#define IPG_TXDMABURSTTHRESH_VALUE 0x30 + +/* RXDMAPollPeriod is specified in 320ns increments. + * + * Value Time + * --------------------- + * 0x00-0x01 320ns + * 0x03 ~1us + * 0x1F ~10us + * 0xFF ~82us + */ +#define IPG_RXDMAPOLLPERIOD_VALUE 0x01 +#define IPG_RXEARLYTHRESH_VALUE 0x07FF + +/* RxDMAUrgentThresh specifies the minimum amount of + * free space within the receive FIFO before asserting + * a urgent receive DMA request. + * + * Value Min RxFIFO free space before urgent RX request + * --------------------------------------------------------------- + * 0x00-0x04 128 bytes (1024 bits) + * 0x27 1248 bytes (~10000 bits) + * 0x30 1536 bytes (12288 bits) + * 0xFF 8192 bytes (65535 bits) + */ +#define IPG_RXDMAURGENTTHRESH_VALUE 0x30 + +/* RxDMABurstThresh specifies the minimum amount of + * occupied space within the receive FIFO before asserting + * a receive DMA request. + * + * Value Min TxFIFO free space before TX request + * ---------------------------------------------------- + * 0x00-0x08 256 bytes + * 0x30 1536 bytes + * 0xFF 8192 bytes + */ +#define IPG_RXDMABURSTTHRESH_VALUE 0x30 + +/* FlowOnThresh specifies the maximum amount of occupied + * space in the receive FIFO before a PAUSE frame with + * maximum pause time transmitted. + * + * Value Max RxFIFO occupied space before PAUSE + * --------------------------------------------------- + * 0x0000 0 bytes + * 0x0740 29,696 bytes + * 0x07FF 32,752 bytes + */ +#define IPG_FLOWONTHRESH_VALUE 0x0740 + +/* FlowOffThresh specifies the minimum amount of occupied + * space in the receive FIFO before a PAUSE frame with + * zero pause time is transmitted. + * + * Value Max RxFIFO occupied space before PAUSE + * --------------------------------------------------- + * 0x0000 0 bytes + * 0x00BF 3056 bytes + * 0x07FF 32,752 bytes + */ +#define IPG_FLOWOFFTHRESH_VALUE 0x00BF + +/* end ipg_tune.h */ diff --git a/drivers/net/ip1000a/make2.2.sh b/drivers/net/ip1000a/make2.2.sh new file mode 100644 index 0000000..388a351 --- /dev/null +++ b/drivers/net/ip1000a/make2.2.sh @@ -0,0 +1 @@ +gcc -DMODULE -D__KERNEL__ -I /usr/src/linux/include -Wall -Wstrict-prototypes -DIPG_TMI_FIBER_DETECT -O6 -c -c ipg.c -o ipg.o diff --git a/drivers/net/ip1000a/make2.2mod.sh b/drivers/net/ip1000a/make2.2mod.sh new file mode 100644 index 0000000..0149279 --- /dev/null +++ b/drivers/net/ip1000a/make2.2mod.sh @@ -0,0 +1 @@ +gcc -DMODULE -D__KERNEL__ -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -I /usr/src/linux/include/net -Wall -Wstrict-prototypes -DIPG_TMI_FIBER_DETECT -O6 -c -c ipg.c -o ipg.o diff --git a/drivers/net/ip1000a/readme.txt b/drivers/net/ip1000a/readme.txt new file mode 100644 index 0000000..36d8cca --- /dev/null +++ b/drivers/net/ip1000a/readme.txt @@ -0,0 +1,141 @@ + + IC Plus IP1000 Gigabit Ethernet Adapter + Linux driver + +Contents: +----------- +1. File Description +2. Driver Installation for Linux +3. Jumbo Support + +1. File Description +------------------- + +Filename Description +==================== ======================================================= +ipg.c IC Plus IP1000 Linux Driver Source Code. + This file is the main part of IP1000 Linux Driver. + +makefile Make File For IP1000 Linux Driver. + Using "make all", "make smp", "make bigmem" for your + kernel. + +make2.2.sh Make Shell Script For Linux 2.2.x Kernel. + +make2.2mod.sh Make Shell Script For Linux 2.2.x Kernel. + +PhyParam.h IP1000 Hardware Parameters modification file. + It would have new version for new version of NIC on IC + Plus web site. + +ipg_tune.h Include File For IP1000 Linux Driver. + +ipg_structs.h Include File For IP1000 Linux Driver. + +ipg_macros.h Include File For IP1000 Linux Driver. + +ipg_constants.h Include File For IP1000 Linux Driver. + +readme.txt A summary of the contents for Linux Driver. + This file, which you are reading me now. + + + +2. Driver Installation for Linux +----------------------------------------- +a. for kernel 2.4.x + a1. Redhat 7.3 (linux kernel 2.4.18) + a2. Mandrake 8.1 (kernel 2.4.8) +b. for kernel 2.6.x +c. for bigmem and smp. + + a.for kernel 2.4.x + ------------------- + a1. Redhat 7.3 (linux kernel 2.4.18) + a1.1. install way 1: + #make all =>generate ipg.o + #cp ipg.o /lib/modules/2.4.18-3/kernel/drivers/net/ + #insmod ./ipg.o + #ifconfig eth0 xxx.xxx.xxx.xxx netmask yyy.yyy.yyy.yyy + eth0 is your network adapter,use "dmesg" to check it, + ex: eth0, eth1... + xxx is your ip address, ex: 192.168.102.211 + yyy is your netmask address, ex:255.255.255.0 + + a1.2. install way 2: + #make all =>generate ipg.o + #cp ipg.o /lib/modules/2.4.18-3/kernel/drivers/net/ + #insmod ./ipg.o + #setup + [network configuration] =>to setup your ip address + #ifup eth0 + eth0 is your network adapter, ex: eth0, eth1... + + + a2. Mandrake 8.1 (kernel 2.4.8) + #make all => generate ipg.o + #cp ipg.o /lib/modules/2.4.8-26mdk/kernel/drivers/net + #insmod ./ipg.o + #ifconfig eth0 xxx.xxx.xxx.xxx netmask yyy.yyy.yyy.yyy + eth0 is your network adapter,use "dmesg" to check it, + ex: eth0, eth1... + xxx is your ip address, ex: 192.168.102.211 + yyy is your netmask address, ex:255.255.255.0 + + b. for kernel 2.6.x + ------------------- + #make all => generate ipg.ko + #insmod ./ipg.ko + #ifconfig eth0 xxx.xxx.xxx.xxx netmask yyy.yyy.yyy.yyy + eth0 is your network adapter,use "dmesg" to check it, ex: eth0, eth1... + xxx is your ip address, ex: 192.168.102.211 + yyy is your netmask address, ex:255.255.255.0 + ======================================================================== + example for Mandrake 10 automatically load: + #make all => generate ipg.ko + #uname -r + #2.6.11-6mdk => Depending on various Linux versions + #cp ipg.o /lib/modules/2.6.11-6mdk/kernel/drivers/net => Just for Mandrake 10 example. + #insmod ./ipg.ko (or ipg.o) + #ifconfig eth0 xxx.xxx.xxx.xxx netmask yyy.yyy.yyy.yyy + ======================================================================== + + c. for bigmem and smp. + ---------------------- + c1. If your kernel was in bigmem, using: + #make bigmem + + c2. If your kernel was in smp, using: + #make smp + + +3. Jumbo Support +---------------------- + +In Makefile: +3.1. Open Jumbo Support: +MAPPING_MODE= -DUSE_IO_OPS -DJUMBO_FRAME + +3.2. Close Jumbo Support +MAPPING_MODE= -DUSE_IO_OPS + +3.3. Jumbo Support for RX 10K and TX 10K +3.3.1. Change max jumbo frame support size, please change JUMBO_FRAME_SIZE_xxxx option to modify + support size, the more large frame support need more memory to use, the best performence for + IP1000A may be "JUMBO_FRAME_SIZE_4K". + + Note: After changed JUMBO_FRAME_SIZE_xxxx option, please "make clean" then "make" again. + +in Makefile: +MAPPING_MODE= -DUSE_IO_OPS -DJUMBO_FRAME -DJUMBO_FRAME_SIZE_4K + +Usiable options: +JUMBO_FRAME_SIZE_2K +JUMBO_FRAME_SIZE_3K +JUMBO_FRAME_SIZE_4K +JUMBO_FRAME_SIZE_5K +JUMBO_FRAME_SIZE_6K +JUMBO_FRAME_SIZE_7K +JUMBO_FRAME_SIZE_8K +JUMBO_FRAME_SIZE_9K +JUMBO_FRAME_SIZE_10K \ No newline at end of file -- 2.20.1