diff options
author | John Crispin <blogic@openwrt.org> | 2012-10-17 22:45:58 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2012-10-17 22:45:58 +0000 |
commit | 16ed01db05cf25221a62baf3c8eba135f933a6b1 (patch) | |
tree | 405d52924fbc92967e8681bcca5e9c17d35aab8c /package/system | |
parent | 2372b1dbdb253065274b8a54846149d634bcea14 (diff) | |
download | upstream-16ed01db05cf25221a62baf3c8eba135f933a6b1.tar.gz upstream-16ed01db05cf25221a62baf3c8eba135f933a6b1.tar.bz2 upstream-16ed01db05cf25221a62baf3c8eba135f933a6b1.zip |
[kernel] move lots of kernel related packages to the new system/ folder
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33830 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/system')
154 files changed, 46210 insertions, 0 deletions
diff --git a/package/system/ar7-atm/Config.in b/package/system/ar7-atm/Config.in new file mode 100644 index 0000000000..479b7ad072 --- /dev/null +++ b/package/system/ar7-atm/Config.in @@ -0,0 +1,22 @@ +menu "Configuration" + depends on (PACKAGE_kmod-sangam-atm-annex-a || PACKAGE_kmod-sangam-atm-annex-b) + +choice + prompt "Firmware version" + default AR7_ATM_FW_VERSION_704 + help + This option allows you to switch between firmware/driver versions which + might improve the DSL line speed. + +config AR7_ATM_FW_VERSION_705 + bool "D7.05.01.00" + +config AR7_ATM_FW_VERSION_704 + bool "D7.04.03.00" + +config AR7_ATM_FW_VERSION_703 + bool "D7.03.01.00" + +endchoice + +endmenu diff --git a/package/system/ar7-atm/Makefile b/package/system/ar7-atm/Makefile new file mode 100644 index 0000000000..e9c3864876 --- /dev/null +++ b/package/system/ar7-atm/Makefile @@ -0,0 +1,100 @@ +# +# Copyright (C) 2006-2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=sangam_atm + +ifeq ($(CONFIG_AR7_ATM_FW_VERSION_705),y) +PKG_VERSION:=D7.05.01.00 +PKG_MD5SUM:=42ee465be5cfbe9476fc25deb260d450 +PKG_RELEASE:=R1 +PATCH_DIR:=patches-$(PKG_VERSION) +endif + +ifeq ($(CONFIG_AR7_ATM_FW_VERSION_704),y) +PKG_VERSION:=D7.04.03.00 +PKG_MD5SUM:=3d76004e46f09e88931f91670cb420ad +PKG_RELEASE:=R1 +PATCH_DIR:=patches-$(PKG_VERSION) +endif + +ifeq ($(CONFIG_AR7_ATM_FW_VERSION_703),y) +PKG_VERSION:=D7.03.01.00 +PKG_MD5SUM:=bc6e9c6adb1be25820c7ee661de8ca7d +PKG_RELEASE:=R2 +PATCH_DIR:=patches-D7.04.03.00 +endif + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE).tar.bz2 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/sangam-atm/Default + SUBMENU:=Network Devices + DEPENDS:=@TARGET_ar7 +kmod-atm + TITLE:=AR7 ADSL driver + FILES:=$(PKG_BUILD_DIR)/tiatm.ko + AUTOLOAD:=$(call AutoLoad,50,tiatm) + MAINTAINER:=Florian Fainelli <florian@openwrt.org> + MENU:=1 +endef + +define KernelPackage/sangam-atm/config + source "$(SOURCE)/Config.in" +endef + +define KernelPackage/sangam-atm-annex-a +$(call KernelPackage/sangam-atm/Default) + TITLE+= (Annex A, ADSL over POTS) +endef + +define KernelPackage/sangam-atm-annex-a/description + The AR7 ADSL driver for Annex A (ADSL over POTS). +endef + +define KernelPackage/sangam-atm-annex-a/config +$(call KernelPackage/sangam-atm/config) +endef + +define KernelPackage/sangam-atm-annex-b +$(call KernelPackage/sangam-atm/Default) + TITLE+= (Annex B, ADSL over ISDN) +endef + +define KernelPackage/sangam-atm-annex-b/description + The AR7 ADSL driver for Annex B (ADSL over ISDN). +endef + +define KernelPackage/sangam-atm-annex-a/config +$(call KernelPackage/sangam-atm/config) +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + modules +endef + +define KernelPackage/sangam-atm-annex-a/install + mkdir -p $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/ar0700mp.bin $(1)/lib/firmware/ + ln -sf ar0700mp.bin $(1)/lib/firmware/ar0700xx.bin +endef + +define KernelPackage/sangam-atm-annex-b/install + mkdir -p $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/ar0700db.bin $(1)/lib/firmware/ + ln -sf ar0700db.bin $(1)/lib/firmware/ar0700xx.bin +endef + +$(eval $(call KernelPackage,sangam-atm-annex-a)) +$(eval $(call KernelPackage,sangam-atm-annex-b)) diff --git a/package/system/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch b/package/system/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch new file mode 100644 index 0000000000..df5fe53967 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/100-compile_fix.patch @@ -0,0 +1,768 @@ +--- a/cppi_cpaal5.c ++++ b/cppi_cpaal5.c +@@ -352,7 +352,7 @@ static int halRxReturn(HAL_RECEIVEINFO * + { + /* malloc failed, add this RCB to Needs Buffer List */ + TempRcb->FragCount = 1; /*MJH+030417*/ +- (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */ ++ TempRcb->Eop = TempRcb; /* GSG +030430 */ + + if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */ + { /* +MJH 030410 */ +--- a/dsl_hal_api.c ++++ b/dsl_hal_api.c +@@ -254,15 +254,15 @@ + * of phyEnableDisableWord & phyControlWord to avoid changing API struct + * which may cause change required to application data structure. + ******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + #ifndef NO_ADV_STATS +-#include <dsl_hal_logtable.h> ++#include "dsl_hal_logtable.h" + #endif + +-#include <dsl_hal_version.h> ++#include "dsl_hal_version.h" + + // UR8_MERGE_START CQ11054 Jack Zhang + static unsigned int highprecision_selected = 0; //By default we use low precision for backward compt. +--- a/dsl_hal_support.c ++++ b/dsl_hal_support.c +@@ -140,9 +140,9 @@ + * oamFeature are overriden + // UR8_MERGE_END CQ10774 Ram + *******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + #define NUM_READ_RETRIES 3 + static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits); +--- a/dsl_hal_support.h ++++ b/dsl_hal_support.h +@@ -49,7 +49,7 @@ + * 04Nov05 0.11.00 CPH Fixed T1413 mode got Zero DS/US rate when DSL_BIT_TMODE is set. + *******************************************************************************/ + +-#include <dsl_hal_api.h> ++#include "dsl_hal_api.h" + + #define virtual2Physical(a) (((int)a)&~0xe0000000) + /* External Function Prototype Declarations */ +--- a/Makefile ++++ b/Makefile +@@ -1,18 +1,9 @@ +-# File: drivers/atm/ti_evm3/Makefile + # +-# Makefile for the Texas Instruments EVM3 ADSL/ATM driver. ++# Makefile for the TIATM device driver. + # +-# +-# Copyright (c) 2000 Texas Instruments Incorporated. +-# Jeff Harrell (jharrell@telogy.com) +-# Viren Balar (vbalar@ti.com) +-# Victor Wells (vwells@telogy.com) +-# +-include $(TOPDIR)/Rules.make +- +- +- +- +- +- + ++CONFIG_SANGAM_ATM=m ++#EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++obj-$(CONFIG_SANGAM_ATM) := tiatm.o ++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -61,7 +61,6 @@ + * UR8_MERGE_END CQ11057* + *********************************************************************************************/ + +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -69,11 +68,14 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++ ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> ++ + #include "dsl_hal_api.h" + #include "tn7atm.h" + #include "tn7api.h" +@@ -82,6 +84,7 @@ + #include "dsl_hal_register.h" + + #ifdef MODULE ++MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver"); + MODULE_AUTHOR ("Zhicheng Tang"); + #endif +@@ -100,9 +103,9 @@ MODULE_AUTHOR ("Zhicheng Tang"); + + /*end of externs */ + +-#ifndef TI_STATIC_ALLOCATIONS +-#define TI_STATIC_ALLOCATIONS +-#endif ++//#ifndef TI_STATIC_ALLOCATIONS ++//#define TI_STATIC_ALLOCATIONS ++//#endif + + #define tn7atm_kfree_skb(x) dev_kfree_skb(x) + +@@ -114,7 +117,7 @@ static int EnableQoS = FALSE; + /* prototypes */ + static int tn7atm_set_can_support_adsl2 (int can); + +-static int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci); ++static int tn7atm_open (struct atm_vcc *vcc); + + static void tn7atm_close (struct atm_vcc *vcc); + +@@ -257,13 +260,12 @@ static const struct atmdev_ops tn7atm_op + getsockopt: NULL, + setsockopt: NULL, + send: tn7atm_send, +- sg_send: NULL, + phy_put: NULL, + phy_get: NULL, + change_qos: tn7atm_change_qos, + }; + +-const char drv_proc_root_folder[] = "avalanche/"; ++const char drv_proc_root_folder[] = "avalanche"; + static struct proc_dir_entry *root_proc_dir_entry = NULL; + #define DRV_PROC_MODE 0644 + static int proc_root_already_exists = TRUE; +@@ -559,56 +561,6 @@ static int turbodsl_check_priority_type( + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * +- * Function: int tn7atm_walk_vccs(struct atm_dev *dev, short *vcc, int *vci) +- * +- * Description: retrieve VPI/VCI for connection +- * +- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static int tn7atm_walk_vccs (struct atm_vcc *vcc, short *vpi, int *vci) +-{ +- struct atm_vcc *walk; +- +- /* +- * find a free VPI +- */ +- if (*vpi == ATM_VPI_ANY) +- { +- +- for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) +- { +- +- if ((walk->vci == *vci) && (walk->vpi == *vpi)) +- { +- (*vpi)++; +- walk = vcc->dev->vccs; +- } +- } +- } +- +- /* +- * find a free VCI +- */ +- if (*vci == ATM_VCI_ANY) +- { +- +- for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; +- walk = walk->next) +- { +- +- if ((walk->vpi = *vpi) && (walk->vci == *vci)) +- { +- *vci = walk->vci + 1; +- walk = vcc->dev->vccs; +- } +- } +- } +- +- return 0; +-} +- +- +-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- * + * Function: int tn7atm_sar_irq(void) + * + * Description: tnetd73xx SAR interrupt. +@@ -693,7 +645,7 @@ static int __init tn7atm_irq_request (st + * Register SAR interrupt + */ + priv->sar_irq = LNXINTNUM (ATM_SAR_INT); /* Interrupt line # */ +- if (request_irq (priv->sar_irq, tn7atm_sar_irq, SA_INTERRUPT, "SAR ", dev)) ++ if (request_irq (priv->sar_irq, tn7atm_sar_irq, IRQF_DISABLED, "SAR ", dev)) + printk ("Could not register tn7atm_sar_irq\n"); + + /* +@@ -704,14 +656,14 @@ static int __init tn7atm_irq_request (st + { + def_sar_inter_pace = os_atoi (ptr); + } +- avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, +- def_sar_inter_pace); ++/* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, ++ def_sar_inter_pace);*/ + + /* + * Reigster Receive interrupt A + */ + priv->dsl_irq = LNXINTNUM (ATM_DSL_INT); /* Interrupt line # */ +- if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, SA_INTERRUPT, "DSL ", dev)) ++ if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, IRQF_DISABLED, "DSL ", dev)) + printk ("Could not register tn7atm_dsl_irq\n"); + + /***** VRB Tasklet Mode ****/ +@@ -875,11 +827,15 @@ static int __init tn7atm_get_ESI (struct + #define ATM_VBR_RT 5 + #endif + +-int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci) ++int tn7atm_open (struct atm_vcc *vcc) + { + tn7atm_activate_vc_parm_t tn7atm_activate_vc_parm; + int rc; + //int flags; ++ tn7atm_activate_vc_parm.pcr = 0x20000; ++ tn7atm_activate_vc_parm.scr = 0x20000; ++ tn7atm_activate_vc_parm.mbs = 0x20000; ++ tn7atm_activate_vc_parm.cdvt = 10000; + + dgprintf(1, "tn7atm_open()\n"); + +@@ -891,24 +847,18 @@ int tn7atm_open (struct atm_vcc *vcc, sh + return -1; + } + +- MOD_INC_USE_COUNT; ++// MOD_INC_USE_COUNT; + +- /* find a free VPI/VCI */ +- tn7atm_walk_vccs(vcc, &vpi, &vci); +- +- vcc->vpi = vpi; +- vcc->vci = vci; +- +- if ((vci == ATM_VCI_UNSPEC) || (vpi == ATM_VCI_UNSPEC)) ++ if ((vcc->vci == ATM_VCI_UNSPEC) || (vcc->vpi == ATM_VCI_UNSPEC)) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + return -EBUSY; + } + +- tn7atm_activate_vc_parm.vpi = vpi; +- tn7atm_activate_vc_parm.vci = vci; ++ tn7atm_activate_vc_parm.vpi = vcc->vpi; ++ tn7atm_activate_vc_parm.vci = vcc->vci; + +- if ((vpi == CLEAR_EOC_VPI) && (vci == CLEAR_EOC_VCI)) ++ if ((vcc->vpi == CLEAR_EOC_VPI) && (vcc->vci == CLEAR_EOC_VCI)) + { + /* always use (max_dma_chan+1) for clear eoc */ + tn7atm_activate_vc_parm.chan = EOC_DMA_CHAN; +@@ -916,7 +866,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + /* check to see whether clear eoc is opened or not */ + if (tn7atm_activate_vc_parm.priv->lut[tn7atm_activate_vc_parm.chan].inuse) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + printk("tn7atm_open: Clear EOC channel (dmachan=%d) already in use.\n", tn7atm_activate_vc_parm.chan); + return -EBUSY; + } +@@ -925,7 +875,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + if (rc) + { + printk("tn7atm_open: failed to setup clear_eoc\n"); +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + return -EBUSY; + } + tn7atm_set_lut(tn7atm_activate_vc_parm.priv,vcc, tn7atm_activate_vc_parm.chan); +@@ -934,17 +884,17 @@ int tn7atm_open (struct atm_vcc *vcc, sh + } + else /* PVC channel setup */ + { +- if ((vpi==REMOTE_MGMT_VPI) && (vci==REMOTE_MGMT_VCI)) ++ if ((vcc->vpi==REMOTE_MGMT_VPI) && (vcc->vci==REMOTE_MGMT_VCI)) + { + tn7atm_activate_vc_parm.chan = 14; /* always use chan 14 for MII PVC-base romote mgmt */ + } + else + { +- rc = tn7atm_lut_find(vpi, vci); ++ rc = tn7atm_lut_find(vcc->vpi, vcc->vci); + /* check to see whether PVC is opened or not */ + if(ATM_NO_DMA_CHAN != rc) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + printk("PVC already opened. dmachan = %d\n", rc); + return -EBUSY; + } +@@ -976,6 +926,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + tn7atm_activate_vc_parm.priority = 2; + break; + ++#if 0 + case ATM_VBR: /* Variable Bit Rate-Non RealTime*/ + tn7atm_activate_vc_parm.qos = 1; + tn7atm_activate_vc_parm.priority = 1; +@@ -997,6 +948,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + tn7atm_activate_vc_parm.mbs = vcc->qos.txtp.max_pcr; + tn7atm_activate_vc_parm.cdvt = vcc->qos.txtp.max_cdv; + break; ++#endif + + default: + tn7atm_activate_vc_parm.qos = 2; +@@ -1024,7 +976,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + if (rc < 0) + { + printk("failed to activate hw channel\n"); +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + tn7atm_lut_clear(vcc, tn7atm_activate_vc_parm.chan); + //spin_unlock_irqrestore(&chan_init_lock, flags); + return -EBUSY; +@@ -1114,7 +1066,7 @@ void tn7atm_close (struct atm_vcc *vcc) + tn7atm_lut_clear (vcc, dmachan); + //spin_unlock_irqrestore (&closeLock, closeFlag); + +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + + dgprintf (1, "Leave tn7atm_close\n"); + } +@@ -1528,8 +1480,7 @@ int tn7atm_receive (void *os_dev, int ch + * firewall is on */ + + dgprintf (3, "pushing the skb...\n"); +- +- skb->stamp = vcc->timestamp = xtime; ++ __net_timestamp(skb); + + xdump ((unsigned char *) skb->data, skb->len, 5); + +@@ -1725,8 +1676,7 @@ static void tn7atm_exit (void) + + kfree (dev->dev_data); + +- // atm_dev_deregister (dev); +- shutdown_atm_dev (dev); ++ atm_dev_deregister (dev); + + /* + * remove proc entries +@@ -1885,9 +1835,6 @@ static int __init tn7atm_detect (void) + /* + * Set up proc entry for atm stats + */ +- if (tn7atm_xlate_proc_name +- (drv_proc_root_folder, &root_proc_dir_entry, &residual)) +- { + printk ("Creating new root folder %s in the proc for the driver stats \n", + drv_proc_root_folder); + root_proc_dir_entry = proc_mkdir (drv_proc_root_folder, NULL); +@@ -1897,7 +1844,6 @@ static int __init tn7atm_detect (void) + return -ENOMEM; + } + proc_root_already_exists = FALSE; +- } + + /* + * AV: Clean-up. Moved all the definitions to the data structure. +@@ -2479,7 +2425,5 @@ static int tn7atm_proc_qos_write(struct + return count; + } + +-#ifdef MODULE + module_init (tn7atm_detect); + module_exit (tn7atm_exit); +-#endif /* MODULE */ +--- a/tn7atm.h ++++ b/tn7atm.h +@@ -19,7 +19,8 @@ + //#include "mips_support.h" + #include <linux/list.h> + +-#include <linux/config.h> ++#define MIPS_EXCEPTION_OFFSET 8 ++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET) + + #ifdef CONFIG_MODVERSIONS + #include <linux/modversions.h> +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -94,7 +94,6 @@ + * 1/02/07 JZ CQ11054: Data Precision and Range Changes for TR-069 Conformance + * UR8_MERGE_END CQ11054* + *********************************************************************************************/ +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -102,8 +101,6 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +@@ -111,6 +108,12 @@ + #include <linux/timer.h> + #include <linux/vmalloc.h> + #include <linux/file.h> ++#include <linux/firmware.h> ++ ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> ++ + /* Modules specific header files */ + #include "tn7atm.h" + #include "tn7api.h" +@@ -173,7 +176,7 @@ led_reg_t ledreg[2]; + static struct led_funcs ledreg[2]; + #endif + +-#define DEV_DSLMOD 1 ++#define DEV_DSLMOD CTL_UNNUMBERED + #define MAX_STR_SIZE 256 + #define DSL_MOD_SIZE 256 + +@@ -299,7 +302,7 @@ static PITIDSLHW_T pIhw; + static volatile int bshutdown; + static char info[MAX_STR_SIZE]; + /* Used for DSL Polling enable */ +-static DECLARE_MUTEX_LOCKED (adsl_sem_overlay); ++static struct semaphore adsl_sem_overlay; + + //kthread_t overlay_thread; + /* end of module wide declars */ +@@ -323,6 +326,14 @@ static int tn7dsl_proc_snr_print (char * + #define gDot1(a) ((a>0)?(a%10):((-a)%10)) + // UR8_MERGE_END CQ11054* + ++int avalanche_request_intr_pacing(int irq_nr, unsigned int blk_num, ++ unsigned int pace_value) ++{ ++ printk("avalanche_request_pacing(%d, %u, %u); // not implemented\n", irq_nr, blk_num, pace_value); ++ return 0; ++} ++ ++ + int os_atoi(const char *pStr) + { + int MulNeg = (*pStr == '-' ? -1 : 1); +@@ -359,39 +370,6 @@ void dprintf (int uDbgLevel, char *szFmt + #endif + } + +-int strcmp(const char *s1, const char *s2) +-{ +- +- int size = strlen(s1); +- +- return(strncmp(s1, s2, size)); +-} +- +-int strncmp(const char *s1, const char *s2, size_t size) +-{ +- int i = 0; +- int max_size = (int)size; +- +- while((s1[i] != 0) && i < max_size) +- { +- if(s2[i] == 0) +- { +- return -1; +- } +- if(s1[i] != s2[i]) +- { +- return 1; +- } +- i++; +- } +- if(s2[i] != 0) +- { +- return 1; +- } +- +- return 0; +-} +- + // * UR8_MERGE_START CQ10640 Jack Zhang + int tn7dsl_dump_dsp_memory(char *input_str) //cph99 + { +@@ -441,101 +419,74 @@ unsigned int shim_osGetCpuFrequency(void + return CpuFrequency; + } + +-int shim_osLoadFWImage(unsigned char *ptr) ++static void avsar_release(struct device *dev) + { +- unsigned int bytesRead; +- mm_segment_t oldfs; +- static struct file *filp; +- unsigned int imageLength=0x5ffff; +- +- +- dgprintf(4, "tn7dsl_read_dsp()\n"); +- +- dgprintf(4,"open file %s\n", DSP_FIRMWARE_PATH); +- +- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY); +- if(filp ==NULL) +- { +- printk("Failed: Could not open DSP binary file\n"); +- return -1; +- } +- +- if (filp->f_dentry != NULL) +- { +- if (filp->f_dentry->d_inode != NULL) +- { +- printk ("DSP binary filesize = %d bytes\n", +- (int) filp->f_dentry->d_inode->i_size); +- imageLength = (unsigned int)filp->f_dentry->d_inode->i_size + 0x200; +- } +- } +- +- if (filp->f_op->read==NULL) +- return -1; /* File(system) doesn't allow reads */ +- +- /* +- * Disable parameter checking +- */ +- oldfs = get_fs(); +- set_fs(KERNEL_DS); +- +- /* +- * Now read bytes from postion "StartPos" +- */ +- filp->f_pos = 0; +- +- bytesRead = filp->f_op->read(filp,ptr,imageLength,&filp->f_pos); +- +- dgprintf(4,"file length = %d\n", bytesRead); +- +- set_fs(oldfs); +- +- /* +- * Close the file +- */ +- fput(filp); +- +- return bytesRead; ++ printk(KERN_DEBUG "avsar firmware released\n"); + } + ++static struct device avsar = { ++ .bus_id = "vlynq", ++ .release = avsar_release, ++}; + +-unsigned int shim_read_overlay_page (void *ptr, unsigned int secOffset, +- unsigned int secLength) ++int shim_osLoadFWImage(unsigned char *ptr) + { +- unsigned int bytesRead; +- mm_segment_t oldfs; +- struct file *filp; +- +- dgprintf(4,"shim_read_overlay_page\n"); +- //dgprintf(4,"sec offset=%d, sec length =%d\n", secOffset, secLength); ++ const struct firmware *fw_entry; ++ size_t size; + +- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY); +- if(filp ==NULL) +- { +- printk("Failed: Could not open DSP binary file\n"); +- return -1; +- } +- +- if (filp->f_op->read==NULL) +- return -1; /* File(system) doesn't allow reads */ +- +- /* +- * Now read bytes from postion "StartPos" +- */ +- +- if(filp->f_op->llseek) +- filp->f_op->llseek(filp,secOffset, 0); +- oldfs = get_fs(); +- set_fs(KERNEL_DS); +- filp->f_pos = secOffset; +- bytesRead = filp->f_op->read(filp,ptr,secLength,&filp->f_pos); +- +- set_fs(oldfs); +- /* +- * Close the file +- */ +- fput(filp); +- return bytesRead; ++ printk("requesting firmware image \"ar0700xx.bin\"\n"); ++ if(device_register(&avsar) < 0) { ++ printk(KERN_ERR ++ "avsar: device_register fails\n"); ++ return -1; ++ } ++ ++ if(request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) { ++ printk(KERN_ERR ++ "avsar: Firmware not available\n"); ++ device_unregister(&avsar); ++ return -1; ++ } ++ size = fw_entry->size; ++ device_unregister(&avsar); ++ if(size > 0x5ffff) { ++ printk(KERN_ERR ++ "avsar: Firmware too big (%d bytes)\n", size); ++ release_firmware(fw_entry); ++ return -1; ++ } ++ memcpy(ptr, fw_entry->data, size); ++ release_firmware(fw_entry); ++ return size; ++} ++ ++unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength) ++{ ++ const struct firmware *fw_entry; ++ ++ printk("requesting firmware image \"ar0700xx.bin\"\n"); ++ if(device_register(&avsar) < 0) { ++ printk(KERN_ERR ++ "avsar: device_register fails\n"); ++ return -1; ++ } ++ ++ if(request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) { ++ printk(KERN_ERR ++ "avsar: Firmware not available\n"); ++ device_unregister(&avsar); ++ return -1; ++ } ++ device_unregister(&avsar); ++ if(fw_entry->size > secLength) { ++ printk(KERN_ERR ++ "avsar: Firmware too big (%d bytes)\n", fw_entry->size); ++ release_firmware(fw_entry); ++ return -1; ++ } ++ memcpy(ptr + secOffset, fw_entry->data, secLength); ++ release_firmware(fw_entry); ++ return secLength; + } + + int shim_osLoadDebugFWImage(unsigned char *ptr) +@@ -3064,6 +3015,7 @@ int tn7dsl_init(void *priv) + int high_precision_selected = 0; + // UR8_MERGE_END CQ11054* + ++ sema_init(&adsl_sem_overlay, 0); + /* + * start dsl + */ +@@ -3442,7 +3394,7 @@ static int dslmod_sysctl(ctl_table *ctl, + */ + if(write) + { +- ret = proc_dostring(ctl, write, filp, buffer, lenp); ++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); + + switch (ctl->ctl_name) + { +@@ -3528,14 +3480,14 @@ static int dslmod_sysctl(ctl_table *ctl, + else + { + len += sprintf(info+len, mod_req); +- ret = proc_dostring(ctl, write, filp, buffer, lenp); ++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); + } + return ret; + } + + + ctl_table dslmod_table[] = { +- {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, &dslmod_sysctl} ++ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string} + , + {0} + }; +@@ -3558,8 +3510,7 @@ void tn7dsl_dslmod_sysctl_register(void) + if (initialized == 1) + return; + +- dslmod_sysctl_header = register_sysctl_table(dslmod_root_table, 1); +- dslmod_root_table->child->de->owner = THIS_MODULE; ++ dslmod_sysctl_header = register_sysctl_table(dslmod_root_table); + + /* + * set the defaults +@@ -4821,4 +4772,4 @@ int tn7dsl_proc_PMDus(char* buf, char ** + } + #endif //NO_ADV_STATS + #endif //TR69_PMD_IN +-// * UR8_MERGE_END CQ11057 * +\ No newline at end of file ++// * UR8_MERGE_END CQ11057 * +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -42,7 +42,6 @@ + * UR8_MERGE_END CQ10700 + *******************************************************************************/ + +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -50,12 +49,13 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> + ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> + + #define _CPHAL_AAL5 + #define _CPHAL_SAR diff --git a/package/system/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch b/package/system/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch new file mode 100644 index 0000000000..9acb862e5d --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/110-interrupt_fix.patch @@ -0,0 +1,37 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -566,7 +566,7 @@ static int turbodsl_check_priority_type( + * Description: tnetd73xx SAR interrupt. + * + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static void tn7atm_sar_irq (int irq, void *voiddev, struct pt_regs *regs) ++static irqreturn_t tn7atm_sar_irq (int irq, void *voiddev) + { + struct atm_dev *atmdev; + Tn7AtmPrivate *priv; +@@ -593,6 +593,7 @@ static void tn7atm_sar_irq (int irq, voi + #ifdef TIATM_INST_SUPP + psp_trace_par (ATM_DRV_SAR_ISR_EXIT, retval); + #endif ++ return IRQ_HANDLED; + } + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +@@ -602,7 +603,7 @@ static void tn7atm_sar_irq (int irq, voi + * Description: tnetd73xx DSL interrupt. + * + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static void tn7atm_dsl_irq (int irq, void *voiddev, struct pt_regs *regs) ++static irqreturn_t tn7atm_dsl_irq (int irq, void *voiddev) + { + struct atm_dev *atmdev; + Tn7AtmPrivate *priv; +@@ -624,6 +625,8 @@ static void tn7atm_dsl_irq (int irq, voi + #ifdef TIATM_INST_SUPP + psp_trace_par (ATM_DRV_DSL_ISR_EXIT, retval); + #endif ++ ++ return IRQ_HANDLED; + } + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/package/system/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch b/package/system/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch new file mode 100644 index 0000000000..2968fdc166 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/120-no_dumb_inline.patch @@ -0,0 +1,11 @@ +--- a/tn7api.h ++++ b/tn7api.h +@@ -107,7 +107,7 @@ int tn7dsl_proc_dbg_rmsgs4(char* buf, ch + + int tn7dsl_proc_write_stats(struct file *fp, const char * buf, unsigned long count, void * data); + int tn7dsl_proc_modem(char* buf, char **start, off_t offset, int count,int *eof, void *data); +-inline int tn7dsl_handle_interrupt(void); ++int tn7dsl_handle_interrupt(void); + + void tn7dsl_dslmod_sysctl_register(void); + void tn7dsl_dslmod_sysctl_unregister(void); diff --git a/package/system/ar7-atm/patches-D7.04.03.00/130-powercutback.patch b/package/system/ar7-atm/patches-D7.04.03.00/130-powercutback.patch new file mode 100644 index 0000000000..ec00df97ab --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/130-powercutback.patch @@ -0,0 +1,44 @@ +--- a/dsl_hal_advcfg.c ++++ b/dsl_hal_advcfg.c +@@ -36,9 +36,9 @@ + * 05Jul05 0.00.09 CPH CQ9775: Change dslhal_advcfg_configDsTones input parameters & support for ADSL2+ + * 24Jul05 0.00.10 CPH Fixed comments in dslhal_advcfg_configDsTones function header + *******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + /*****************************************************************************/ + /* ACT API functions -- To be moved into their own independent module --RamP */ +--- a/Makefile ++++ b/Makefile +@@ -4,6 +4,7 @@ + + CONFIG_SANGAM_ATM=m + #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT +-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL + obj-$(CONFIG_SANGAM_ATM) := tiatm.o +-tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o ++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -2869,6 +2869,14 @@ static int tn7dsl_set_dsl(void) + dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr)); + } + ++ // set powercutback ++ ptr = NULL; ++ ptr = prom_getenv("powercutback"); ++ if(ptr) ++ { ++ dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr)); ++ } ++ + // trellis + ptr = NULL; + ptr = prom_getenv("trellis"); diff --git a/package/system/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch b/package/system/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch new file mode 100644 index 0000000000..ce3697b10d --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/140-debug_mode.patch @@ -0,0 +1,16 @@ +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -103,10 +103,10 @@ enum + + #define RESERVED_OAM_CHANNEL 15 + +-#define AAL5_PARM "id=aal5, base = 0x03000000, offset = 0, int_line=15, ch0=[RxBufSize=1522; RxNumBuffers = 32; RxServiceMax = 50; TxServiceMax=50; TxNumBuffers=32; CpcsUU=0x5aa5; TxVc_CellRate=0x3000; TxVc_AtmHeader=0x00000640]" +-#define SAR_PARM "id=sar,base = 0x03000000, reset_bit = 9, offset = 0; UniNni = 0, PdspEnable = 1" ++#define CH0_PARM "RxBufSize=1522, RxNumBuffers=32, RxServiceMax=50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640" ++#define AAL5_PARM "id=aal5, base=0x03000000, offset=0, int_line=15, ch0=[" CH0_PARM "]" ++#define SAR_PARM "id=sar, base=0x03000000, reset_bit=9, offset=0; UniNni=0, PdspEnable=1, Debug=0xFFFFFFFF" + #define RESET_PARM "id=ResetControl, base=0xA8611600" +-#define CH0_PARM "RxBufSize=1522, RxNumBuffers = 32, RxServiceMax = 50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640" + + #define MAX_PVC_TABLE_ENTRY 16 + diff --git a/package/system/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch b/package/system/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch new file mode 100644 index 0000000000..97b8cecdd9 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/150-tasklet_mode.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -5,6 +5,7 @@ + CONFIG_SANGAM_ATM=m + #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT + #EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL +-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL ++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL -DCPATM_TASKLET_MODE + obj-$(CONFIG_SANGAM_ATM) := tiatm.o + tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o diff --git a/package/system/ar7-atm/patches-D7.04.03.00/160-module-params.patch b/package/system/ar7-atm/patches-D7.04.03.00/160-module-params.patch new file mode 100644 index 0000000000..67802ae1e9 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/160-module-params.patch @@ -0,0 +1,589 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -87,6 +87,146 @@ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver"); + MODULE_AUTHOR ("Zhicheng Tang"); ++ ++int mp_sar_ipacemax = -1; ++module_param_named(ipacemax, mp_sar_ipacemax, int, 0); ++MODULE_PARM_DESC(ipacemax, "Interrupt pacing"); ++ ++char *mp_macc = NULL; ++module_param_named(macc, mp_macc, charp, 0); ++MODULE_PARM_DESC(macc, "MAC address"); ++ ++int mp_dsp_noboost = -1; ++module_param_named(dsp_noboost, mp_dsp_noboost, int, 0); ++MODULE_PARM_DESC(dsp_noboost, "Suppress DSP frequency boost"); ++ ++int mp_dsp_freq = -1; ++module_param_named(dsp_freq, mp_dsp_freq, int, 0); ++MODULE_PARM_DESC(dsp_freq, "Frequency to boost the DSP to"); ++ ++char *mp_featctl0 = NULL; ++module_param_named(featctl0, mp_featctl0, charp, 0); ++MODULE_PARM_DESC(featctl0, "DSL feature control 0"); ++ ++char *mp_featctl1 = NULL; ++module_param_named(featctl1, mp_featctl1, charp, 0); ++MODULE_PARM_DESC(featctl1, "DSL feature control 1"); ++ ++char *mp_phyctl0 = NULL; ++module_param_named(phyctl0, mp_phyctl0, charp, 0); ++MODULE_PARM_DESC(phyctl0, "DSL PHY control 0"); ++ ++char *mp_phyctl1 = NULL; ++module_param_named(phyctl1, mp_phyctl1, charp, 0); ++MODULE_PARM_DESC(phyctl1, "DSL PHY control 1"); ++ ++int mp_turbodsl = -1; ++module_param_named(turbodsl, mp_turbodsl, int, 0); ++MODULE_PARM_DESC(turbodsl, "Enable TurboDSL"); ++ ++int mp_sar_rxbuf = -1; ++module_param_named(sar_rxbuf, mp_sar_rxbuf, int, 0); ++MODULE_PARM_DESC(sar_rxbuf, "SAR RxBuf size"); ++ ++int mp_sar_rxmax = -1; ++module_param_named(sar_rxmax, mp_sar_rxmax, int, 0); ++MODULE_PARM_DESC(sar_rxmax, "SAR RxMax size"); ++ ++int mp_sar_txbuf = -1; ++module_param_named(sar_txbuf, mp_sar_txbuf, int, 0); ++MODULE_PARM_DESC(sar_txbuf, "SAR TxBuf size"); ++ ++int mp_sar_txmax = -1; ++module_param_named(sar_txmax, mp_sar_txmax, int, 0); ++MODULE_PARM_DESC(sar_txmax, "SAR TxMax size"); ++ ++char *mp_modulation = NULL; ++module_param_named(modulation, mp_modulation, charp, 0); ++MODULE_PARM_DESC(modulation, "Modulation"); ++ ++int mp_fine_gain_control = -1; ++module_param_named(fine_gain_control, mp_fine_gain_control, int, 0); ++MODULE_PARM_DESC(fine_gain_control, "Fine gain control"); ++ ++int mp_fine_gain_value = -1; ++module_param_named(fine_gain_value, mp_fine_gain_value, int, 0); ++MODULE_PARM_DESC(fine_gain_value, "Fine gain value"); ++ ++int mp_enable_margin_retrain = -1; ++module_param_named(enable_margin_retrain, mp_enable_margin_retrain, int, 0); ++MODULE_PARM_DESC(enable_margin_retrain, "Enable margin retrain"); ++ ++int mp_margin_threshold = -1; ++module_param_named(margin_threshold, mp_margin_threshold, int, 0); ++MODULE_PARM_DESC(margin_threshold, "Margin retrain treshold"); ++ ++int mp_enable_rate_adapt = -1; ++module_param_named(enable_rate_adapt, mp_enable_rate_adapt, int, 0); ++MODULE_PARM_DESC(enable_rate_adapt, "Enable rate adaption"); ++ ++int mp_powercutback = -1; ++module_param_named(powercutback, mp_powercutback, int, 0); ++MODULE_PARM_DESC(powercutback, "Enable / disable powercutback"); ++ ++int mp_trellis = -1; ++module_param_named(trellis, mp_trellis, int, 0); ++MODULE_PARM_DESC(trellis, "Enable / disable trellis coding"); ++ ++int mp_bitswap = -1; ++module_param_named(bitswap, mp_bitswap, int, 0); ++MODULE_PARM_DESC(bitswap, "Enable / disable bitswap"); ++ ++int mp_maximum_bits_per_carrier = -1; ++module_param_named(maximum_bits_per_carrier, mp_maximum_bits_per_carrier, int, 0); ++MODULE_PARM_DESC(maximum_bits_per_carrier, "Maximum bits per carrier"); ++ ++int mp_maximum_interleave_depth = -1; ++module_param_named(maximum_interleave_depth, mp_maximum_interleave_depth, int, 0); ++MODULE_PARM_DESC(maximum_interleave_depth, "Maximum interleave depth"); ++ ++int mp_pair_selection = -1; ++module_param_named(pair_selection, mp_pair_selection, int, 0); ++MODULE_PARM_DESC(pair_selection, "Pair selection"); ++ ++int mp_dgas_polarity = -1; ++module_param_named(dgas_polarity, mp_dgas_polarity, int, 0); ++MODULE_PARM_DESC(dgas_polarity, "DGAS polarity"); ++ ++int mp_los_alarm = -1; ++module_param_named(los_alarm, mp_los_alarm, int, 0); ++MODULE_PARM_DESC(los_alarm, "LOS alarm"); ++ ++char *mp_eoc_vendor_id = NULL; ++module_param_named(eoc_vendor_id, mp_eoc_vendor_id, charp, 0); ++MODULE_PARM_DESC(eoc_vendor_id, "EOC vendor id"); ++ ++int mp_eoc_vendor_revision = -1; ++module_param_named(eoc_vendor_revision, mp_eoc_vendor_revision, int, 0); ++MODULE_PARM_DESC(eoc_vendor_revision, "EOC vendor revision"); ++ ++char *mp_eoc_vendor_serialnum = NULL; ++module_param_named(eoc_vendor_serialnum, mp_eoc_vendor_serialnum, charp, 0); ++MODULE_PARM_DESC(eoc_vendor_serialnum, "EOC vendor serial number"); ++ ++char *mp_invntry_vernum = NULL; ++module_param_named(invntry_vernum, mp_invntry_vernum, charp, 0); ++MODULE_PARM_DESC(invntry_vernum, "Inventory revision number"); ++ ++int mp_dsl_bit_tmode = -1; ++module_param_named(dsl_bit_tmode, mp_dsl_bit_tmode, int, 0); ++MODULE_PARM_DESC(dsl_bit_tmode, "DSL bit training mode"); ++ ++int mp_high_precision = -1; ++module_param_named(high_precision, mp_high_precision, int, 0); ++MODULE_PARM_DESC(high_precision, "High precision"); ++ ++int mp_autopvc_enable = -1; ++module_param_named(autopvc_enable, mp_autopvc_enable, int, 0); ++MODULE_PARM_DESC(autopvc_enable, "Enable / disable automatic PVC"); ++ ++int mp_oam_lb_timeout = -1; ++module_param_named(oam_lb_timeout, mp_oam_lb_timeout, int, 0); ++MODULE_PARM_DESC(oam_lb_timeout, "OAM LB timeout"); + #endif + + #ifndef TRUE +@@ -655,9 +795,9 @@ + * interrupt pacing + */ + ptr = prom_getenv ("sar_ipacemax"); +- if (ptr) ++ if (ptr || mp_sar_ipacemax != -1) + { +- def_sar_inter_pace = os_atoi (ptr); ++ def_sar_inter_pace = mp_sar_ipacemax == -1 ? os_atoi (ptr) : mp_sar_ipacemax; + } + /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, + def_sar_inter_pace);*/ +@@ -795,9 +935,18 @@ + { + int i; + char esi_addr[ESI_LEN] = { 0x00, 0x00, 0x11, 0x22, 0x33, 0x44 }; +- char *esiaddr_str = NULL; ++ char *esiaddr_str = mp_macc; + +- esiaddr_str = prom_getenv ("maca"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macdsl"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macc"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("HWA_1"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macb"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("maca"); + + if (!esiaddr_str) + { +@@ -1930,15 +2079,15 @@ + //UR8_MERGE_END CQ10450* + + cp = prom_getenv ("dsp_noboost"); +- if (cp) ++ if (cp || mp_dsp_noboost != -1) + { +- dsp_noboost = os_atoi (cp); ++ dsp_noboost = mp_dsp_noboost == -1 ? os_atoi (cp) : mp_dsp_noboost; + } + + cp = (char *) prom_getenv ("dsp_freq"); +- if (cp) ++ if (cp || mp_dsp_freq != -1) + { +- dspfreq = os_atoi (cp); ++ dspfreq = mp_dsp_freq == -1 ? os_atoi (cp) : mp_dsp_freq; + if (dspfreq == 250) + { + boostDsp = 1; +@@ -2187,8 +2336,9 @@ + // Inter-Op DSL phy Control + // Note the setting of _dsl_Feature_0 and _dsl_Feature_1 must before + // dslhal_api_dslStartup (in tn7dsl_init()). +- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL) ++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL || mp_featctl0 != NULL) + { ++ if (mp_featctl0 != NULL) ptr = mp_featctl0; + if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to + // os_atoh + ptr += 2; +@@ -2196,8 +2346,9 @@ + _dsl_Feature_0_defined = 1; + } + +- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL) ++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL || mp_featctl1 != NULL) + { ++ if (mp_featctl1 != NULL) ptr = mp_featctl1; + if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to + // os_atoh + ptr += 2; +@@ -2209,8 +2360,9 @@ + // DSL phy Feature Control + // Note the setting of _dsl_PhyControl_0 and _dsl_PhyControl_1 must before + // dslhal_api_dslStartup (in tn7dsl_init()). +- if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL) ++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL || mp_phyctl0 != NULL) + { ++ if (mp_phyctl0 != NULL) ptr = mp_phyctl0; + if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to + // os_atoh + ptr += 2; +@@ -2218,8 +2370,9 @@ + _dsl_PhyControl_0_defined = 1; + } + +- if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL) ++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL || mp_phyctl1 != NULL) + { ++ if (mp_phyctl1 != NULL) ptr = mp_phyctl1; + if ((ptr[0] == '0') && (ptr[1] == 'x')) // skip 0x before pass to + // os_atoh + ptr += 2; +@@ -2247,9 +2400,9 @@ + priv->bTurboDsl = 1; + // read config for turbo dsl + ptr = prom_getenv ("TurboDSL"); +- if (ptr) ++ if (ptr || mp_turbodsl != -1) + { +- priv->bTurboDsl = os_atoi (ptr); ++ priv->bTurboDsl = mp_turbodsl == -1 ? os_atoi (ptr) : mp_turbodsl; + } + + // @Added to make Rx buffer number & Service max configurable through +@@ -2257,30 +2410,30 @@ + priv->sarRxBuf = RX_BUFFER_NUM; + ptr = NULL; + ptr = prom_getenv ("SarRxBuf"); +- if (ptr) ++ if (ptr || mp_sar_rxbuf != -1) + { +- priv->sarRxBuf = os_atoi (ptr); ++ priv->sarRxBuf = mp_sar_rxbuf == -1 ? os_atoi (ptr) : mp_sar_rxbuf; + } + priv->sarRxMax = RX_SERVICE_MAX; + ptr = NULL; + ptr = prom_getenv ("SarRxMax"); +- if (ptr) ++ if (ptr || mp_sar_rxmax != -1) + { +- priv->sarRxMax = os_atoi (ptr); ++ priv->sarRxMax = mp_sar_rxmax == -1 ? os_atoi (ptr) : mp_sar_rxmax; + } + priv->sarTxBuf = TX_BUFFER_NUM; + ptr = NULL; + ptr = prom_getenv ("SarTxBuf"); +- if (ptr) ++ if (ptr || mp_sar_txbuf != -1) + { +- priv->sarTxBuf = os_atoi (ptr); ++ priv->sarTxBuf = mp_sar_txbuf == -1 ? os_atoi (ptr) : mp_sar_txbuf; + } + priv->sarTxMax = TX_SERVICE_MAX; + ptr = NULL; + ptr = prom_getenv ("SarTxMax"); +- if (ptr) ++ if (ptr || mp_sar_txmax != -1) + { +- priv->sarTxMax = os_atoi (ptr); ++ priv->sarTxMax = mp_sar_txmax == -1 ? os_atoi (ptr) : mp_sar_txmax; + } + + return 0; +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -136,6 +136,27 @@ + #define NEW_TRAINING_VAL_T1413 128 + #define NEW_TRAINING_VAL_MMODE 255 + ++extern char *mp_modulation; ++extern int mp_fine_gain_control; ++extern int mp_fine_gain_value; ++extern int mp_enable_margin_retrain; ++extern int mp_margin_threshold; ++extern int mp_enable_rate_adapt; ++extern int mp_powercutback; ++extern int mp_trellis; ++extern int mp_bitswap; ++extern int mp_maximum_bits_per_carrier; ++extern int mp_maximum_interleave_depth; ++extern int mp_pair_selection; ++extern int mp_dgas_polarity; ++extern int mp_los_alarm; ++extern char *mp_eoc_vendor_id; ++extern int mp_eoc_vendor_revision; ++extern char *mp_eoc_vendor_serialnum; ++extern char *mp_invntry_vernum; ++extern int mp_dsl_bit_tmode; ++extern int mp_high_precision; ++ + int testflag1 = 0; + extern int __guDbgLevel; + extern sar_stat_t sarStat; +@@ -2818,84 +2839,80 @@ static int tn7dsl_set_dsl(void) + + // modulation + ptr = prom_getenv("modulation"); +- if (ptr) ++ if (ptr || mp_modulation != NULL) + { +- tn7dsl_set_modulation(ptr, FALSE); ++ tn7dsl_set_modulation(mp_modulation == NULL ? ptr : mp_modulation, FALSE); + } + + // Fine Gains + ptr = prom_getenv("fine_gain_control"); +- if (ptr) ++ if (ptr || mp_fine_gain_control != -1) + { +- value = os_atoi(ptr); ++ value = mp_fine_gain_control == -1 ? os_atoi(ptr) : mp_fine_gain_control; + tn7dsl_ctrl_fineGain(value); + } + ptr = NULL; + ptr = prom_getenv("fine_gain_value"); +- if(ptr) +- tn7dsl_set_fineGainValue(os_atoh(ptr)); ++ if(ptr || mp_fine_gain_value != -1) ++ tn7dsl_set_fineGainValue(mp_fine_gain_value == -1 ? os_atoh(ptr) : mp_fine_gain_value); + + // margin retrain + ptr = NULL; + ptr = prom_getenv("enable_margin_retrain"); +- if(ptr) ++ value = mp_enable_margin_retrain == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_enable_margin_retrain; ++ ++ if (value == 1) + { +- value = os_atoi(ptr); +- if(value == 1) ++ dslhal_api_setMarginMonitorFlags(pIhw, 0, 1); ++ bMarginRetrainEnable = 1; ++ //printk("enable showtime margin monitor.\n"); ++ ++ ptr = NULL; ++ ptr = prom_getenv("margin_threshold"); ++ value = mp_margin_threshold == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_margin_threshold; ++ ++ if(value >= 0) + { +- dslhal_api_setMarginMonitorFlags(pIhw, 0, 1); +- bMarginRetrainEnable = 1; +- //printk("enable showtime margin monitor.\n"); +- ptr = NULL; +- ptr = prom_getenv("margin_threshold"); +- if(ptr) +- { +- value = os_atoi(ptr); +- //printk("Set margin threshold to %d x 0.5 db\n",value); +- if(value >= 0) +- { +- dslhal_api_setMarginThreshold(pIhw, value); +- bMarginThConfig=1; +- } +- } ++ dslhal_api_setMarginThreshold(pIhw, value); ++ bMarginThConfig=1; + } + } + + // rate adapt + ptr = NULL; + ptr = prom_getenv("enable_rate_adapt"); +- if(ptr) ++ if(ptr || mp_enable_rate_adapt != -1) + { +- dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr)); ++ dslhal_api_setRateAdaptFlag(pIhw, mp_enable_rate_adapt == -1 ? os_atoi(ptr) : mp_enable_rate_adapt); + } + + // set powercutback + ptr = NULL; + ptr = prom_getenv("powercutback"); +- if(ptr) ++ if(ptr || mp_powercutback != -1) + { +- dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr)); ++ dslhal_advcfg_onOffPcb(pIhw, mp_powercutback == -1 ? os_atoi(ptr) : mp_powercutback); + } + + // trellis + ptr = NULL; + ptr = prom_getenv("trellis"); +- if(ptr) ++ if(ptr || mp_trellis != -1) + { +- dslhal_api_setTrellisFlag(pIhw, os_atoi(ptr)); +- trellis = os_atoi(ptr); ++ trellis = mp_trellis == -1 ? os_atoi(ptr) : mp_trellis; ++ dslhal_api_setTrellisFlag(pIhw, trellis); + //printk("trellis=%d\n"); + } + + // bitswap + ptr = NULL; + ptr = prom_getenv("bitswap"); +- if(ptr) ++ if(ptr || mp_bitswap != -1) + { + int offset[2] = {33, 0}; + unsigned int bitswap; + +- bitswap = os_atoi(ptr); ++ bitswap = mp_bitswap == -1 ? os_atoi(ptr) : mp_bitswap; + + tn7dsl_generic_read(2, offset); + dslReg &= dslhal_support_byteSwap32(0xFFFFFF00); +@@ -2913,46 +2930,47 @@ static int tn7dsl_set_dsl(void) + // maximum bits per carrier + ptr = NULL; + ptr = prom_getenv("maximum_bits_per_carrier"); +- if(ptr) ++ if(ptr || mp_maximum_bits_per_carrier != -1) + { +- dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, os_atoi(ptr)); ++ dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, mp_maximum_bits_per_carrier == -1 ? os_atoi(ptr) : mp_maximum_bits_per_carrier); + } + + // maximum interleave depth + ptr = NULL; + ptr = prom_getenv("maximum_interleave_depth"); +- if(ptr) ++ if(ptr || mp_maximum_interleave_depth != -1) + { +- dslhal_api_setMaxInterleaverDepth(pIhw, os_atoi(ptr)); ++ dslhal_api_setMaxInterleaverDepth(pIhw, mp_maximum_interleave_depth == -1 ? os_atoi(ptr) : mp_maximum_interleave_depth); + } + + // inner and outer pairs + ptr = NULL; + ptr = prom_getenv("pair_selection"); +- if(ptr) ++ if(ptr || mp_pair_selection != -1) + { +- dslhal_api_selectInnerOuterPair(pIhw, os_atoi(ptr)); ++ dslhal_api_selectInnerOuterPair(pIhw, mp_pair_selection == -1 ? os_atoi(ptr) : mp_pair_selection); + } + + ptr = NULL; + ptr = prom_getenv("dgas_polarity"); +- if(ptr) ++ if(ptr || mp_dgas_polarity != -1) + { + dslhal_api_configureDgaspLpr(pIhw, 1, 1); +- dslhal_api_configureDgaspLpr(pIhw, 0, os_atoi(ptr)); ++ dslhal_api_configureDgaspLpr(pIhw, 0, mp_dgas_polarity == -1 ? os_atoi(ptr) : mp_dgas_polarity); + } + + ptr = NULL; + ptr = prom_getenv("los_alarm"); +- if(ptr) ++ if(ptr || mp_los_alarm != -1) + { +- dslhal_api_disableLosAlarm(pIhw, os_atoi(ptr)); ++ dslhal_api_disableLosAlarm(pIhw, mp_los_alarm == -1 ? os_atoi(ptr) : mp_los_alarm); + } + + ptr = NULL; + ptr = prom_getenv("eoc_vendor_id"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_id != NULL) + { ++ ptr = mp_eoc_vendor_id == NULL ? ptr : mp_eoc_vendor_id; + for(i=0;i<8;i++) + { + tmp[0]=ptr[i*2]; +@@ -2977,26 +2995,26 @@ static int tn7dsl_set_dsl(void) + } + ptr = NULL; + ptr = prom_getenv("eoc_vendor_revision"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_revision != -1) + { +- value = os_atoi(ptr); ++ value = mp_eoc_vendor_revision == -1 ? os_atoi(ptr) : mp_eoc_vendor_revision; + //printk("eoc rev=%d\n", os_atoi(ptr)); + dslhal_api_setEocRevisionNumber(pIhw, (char *)&value); + + } + ptr = NULL; + ptr = prom_getenv("eoc_vendor_serialnum"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_serialnum != NULL) + { +- dslhal_api_setEocSerialNumber(pIhw, ptr); ++ dslhal_api_setEocSerialNumber(pIhw, mp_eoc_vendor_serialnum == NULL ? ptr : mp_eoc_vendor_serialnum); + } + + // CQ10037 Added invntry_vernum environment variable to be able to set version number in ADSL2, ADSL2+ modes. + ptr = NULL; + ptr = prom_getenv("invntry_vernum"); +- if(ptr) ++ if(ptr || mp_invntry_vernum != NULL) + { +- dslhal_api_setEocRevisionNumber(pIhw, ptr); ++ dslhal_api_setEocRevisionNumber(pIhw, mp_invntry_vernum == NULL ? ptr : mp_invntry_vernum); + } + + return 0; +@@ -3041,7 +3059,7 @@ int tn7dsl_init(void *priv) + * backward compatibility. + */ + cp = prom_getenv("DSL_BIT_TMODE"); +- if (cp) ++ if (cp || mp_dsl_bit_tmode != -1) + { + printk("%s : env var DSL_BIT_TMODE is set\n", __FUNCTION__); + /* +@@ -3070,9 +3088,9 @@ int tn7dsl_init(void *priv) + + // UR8_MERGE_START CQ11054 Jack Zhang + cp = prom_getenv("high_precision"); +- if (cp) ++ if (cp || mp_high_precision != -1) + { +- high_precision_selected = os_atoi(cp); ++ high_precision_selected = mp_high_precision == -1 ? os_atoi(cp) : mp_high_precision; + } + if ( high_precision_selected) + { +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -74,6 +74,8 @@ typedef void OS_SETUP; + /* PDSP Firmware files */ + #include "tnetd7300_sar_firm.h" + ++extern int mp_oam_lb_timeout; ++extern int mp_autopvc_enable; + + enum + { +@@ -817,9 +819,9 @@ int tn7sar_setup_oam_channel(Tn7AtmPriva + pHalDev = (HAL_DEVICE *)priv->pSarHalDev; + + pauto_pvc = prom_getenv("autopvc_enable"); +- if(pauto_pvc) //CQ10273 ++ if(pauto_pvc || mp_autopvc_enable != -1) //CQ10273 + { +- auto_pvc =tn7sar_strtoul(pauto_pvc, NULL, 10); ++ auto_pvc = mp_autopvc_enable == -1 ? tn7sar_strtoul(pauto_pvc, NULL, 10) : mp_autopvc_enable; + } + + memset(&chInfo, 0xff, sizeof(chInfo)); +@@ -985,9 +987,9 @@ int tn7sar_init(struct atm_dev *dev, Tn7 + + /* read in oam lb timeout value */ + pLbTimeout = prom_getenv("oam_lb_timeout"); +- if(pLbTimeout) ++ if(pLbTimeout || mp_oam_lb_timeout != -1) + { +- lbTimeout =tn7sar_strtoul(pLbTimeout, NULL, 10); ++ lbTimeout = mp_oam_lb_timeout == -1 ? tn7sar_strtoul(pLbTimeout, NULL, 10) : mp_oam_lb_timeout; + oamLbTimeout = lbTimeout; + pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &lbTimeout); + } diff --git a/package/system/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch b/package/system/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch new file mode 100644 index 0000000000..9f1f0fdae4 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/170-bus_id_removal.patch @@ -0,0 +1,30 @@ +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -109,6 +109,7 @@ + #include <linux/vmalloc.h> + #include <linux/file.h> + #include <linux/firmware.h> ++#include <linux/version.h> + + #include <asm/io.h> + #include <asm/ar7/ar7.h> +@@ -446,7 +447,9 @@ static void avsar_release(struct device + } + + static struct device avsar = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + .bus_id = "vlynq", ++#endif + .release = avsar_release, + }; + +@@ -455,6 +458,9 @@ int shim_osLoadFWImage(unsigned char *pt + const struct firmware *fw_entry; + size_t size; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ dev_set_name(&avsar, "avsar"); ++#endif + printk("requesting firmware image \"ar0700xx.bin\"\n"); + if(device_register(&avsar) < 0) { + printk(KERN_ERR diff --git a/package/system/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch b/package/system/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch new file mode 100644 index 0000000000..6bd8f48760 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/180-git_headers_include.patch @@ -0,0 +1,54 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -71,10 +71,16 @@ + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++#include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + #include "dsl_hal_api.h" + #include "tn7atm.h" +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -112,8 +112,13 @@ + #include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + /* Modules specific header files */ + #include "tn7atm.h" +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -52,10 +52,16 @@ + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++#include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + #define _CPHAL_AAL5 + #define _CPHAL_SAR diff --git a/package/system/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch b/package/system/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch new file mode 100644 index 0000000000..11487bf7a6 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/190-2.6.32_proc_fixes.patch @@ -0,0 +1,79 @@ +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -203,7 +203,11 @@ led_reg_t ledreg[2]; + static struct led_funcs ledreg[2]; + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + #define DEV_DSLMOD CTL_UNNUMBERED ++#else ++#define DEV_DSLMOD 0 ++#endif + #define MAX_STR_SIZE 256 + #define DSL_MOD_SIZE 256 + +@@ -3431,9 +3435,16 @@ static int dslmod_sysctl(ctl_table *ctl, + */ + if(write) + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) + ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); +- ++#else ++ ret = proc_dostring(ctl, write, buffer, lenp, 0); ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + switch (ctl->ctl_name) ++#else ++ switch ((long)ctl->extra2) ++#endif + { + case DEV_DSLMOD: + ptr = strpbrk(info, " \t"); +@@ -3517,14 +3528,29 @@ static int dslmod_sysctl(ctl_table *ctl, + else + { + len += sprintf(info+len, mod_req); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) + ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); ++#else ++ ret = proc_dostring(ctl, write, buffer, lenp, 0); ++#endif + } + return ret; + } + + + ctl_table dslmod_table[] = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string} ++#else ++ { ++ .procname = "dslmod", ++ .data = info, ++ .maxlen = DSL_MOD_SIZE, ++ .mode = 0644, ++ .proc_handler = &dslmod_sysctl, ++ .extra2 = (void *)DEV_DSLMOD, ++ } ++#endif + , + {0} + }; +@@ -3532,7 +3558,16 @@ ctl_table dslmod_table[] = { + /* Make sure that /proc/sys/dev is there */ + ctl_table dslmod_root_table[] = { + #ifdef CONFIG_PROC_FS ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + {CTL_DEV, "dev", NULL, 0, 0555, dslmod_table} ++ #else ++ { ++ .procname = "dev", ++ .maxlen = 0, ++ .mode = 0555, ++ .child = dslmod_table, ++ } ++ #endif + , + #endif /* CONFIG_PROC_FS */ + {0} diff --git a/package/system/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch b/package/system/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch new file mode 100644 index 0000000000..59c1d58d15 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/200-2.6.37_args.patch @@ -0,0 +1,36 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -1867,7 +1867,11 @@ static int __init tn7atm_register (Tn7At + + dgprintf (4, "device %s being registered\n", priv->name); + ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + mydev = atm_dev_register (priv->proc_name, &tn7atm_ops, -1, NULL); ++ #else ++ mydev = atm_dev_register (priv->proc_name, NULL, &tn7atm_ops, -1, NULL); ++ #endif + + if (mydev == NULL) + { +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -466,14 +466,17 @@ int shim_osLoadFWImage(unsigned char *pt + { + const struct firmware *fw_entry; + size_t size; ++ int ret; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + dev_set_name(&avsar, "avsar"); + #endif + printk("requesting firmware image \"ar0700xx.bin\"\n"); +- if(device_register(&avsar) < 0) { ++ dev_set_name(&avsar, "avsar"); ++ ret = device_register(&avsar); ++ if (ret < 0) { + printk(KERN_ERR +- "avsar: device_register fails\n"); ++ "avsar: device_register fails, error%i\n", ret); + return -1; + } + diff --git a/package/system/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch b/package/system/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch new file mode 100644 index 0000000000..525218c3b4 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.04.03.00/210-3.3-remove-smp_lock.h.patch @@ -0,0 +1,33 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -67,7 +67,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -48,7 +48,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -100,7 +100,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> diff --git a/package/system/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch b/package/system/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch new file mode 100644 index 0000000000..7dee220256 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/100-compile_fix.patch @@ -0,0 +1,808 @@ +--- a/cppi_cpaal5.c ++++ b/cppi_cpaal5.c +@@ -360,7 +360,7 @@ static int halRxReturn(HAL_RECEIVEINFO * + { + /* malloc failed, add this RCB to Needs Buffer List */ + TempRcb->FragCount = 1; /*MJH+030417*/ +- (HAL_RCB *)TempRcb->Eop = TempRcb; /* GSG +030430 */ ++ TempRcb->Eop = TempRcb; /* GSG +030430 */ + + if(HalDev->NeedsCount < MAX_NEEDS) /* +MJH 030410 */ + { /* +MJH 030410 */ +--- a/dsl_hal_api.c ++++ b/dsl_hal_api.c +@@ -273,15 +273,15 @@ + * 09/15/07 CPH CQ11466 Added EFM support + * 09/27/07 EYin CQ11929: Added NFEC/INP/Lp/Rp reporting for only ADSL2/2+ mode. + ******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + #ifndef NO_ADV_STATS +-#include <dsl_hal_logtable.h> ++#include "dsl_hal_logtable.h" + #endif + +-#include <dsl_hal_version.h> ++#include "dsl_hal_version.h" + + // UR8_MERGE_START CQ11054 Jack Zhang + static unsigned int highprecision_selected = 0; //By default we use low precision for backward compt. +--- a/dsl_hal_support.c ++++ b/dsl_hal_support.c +@@ -142,9 +142,9 @@ + * UR8_MERGE_START_END CQ11922 Tim + * 04Sep07 0.14.00 Tim CQ11922: Added support for new scratchram for INP NDR tables + *******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + #define NUM_READ_RETRIES 3 + static unsigned int dslhal_support_adsl2ByteSwap32(unsigned int in32Bits); +--- a/dsl_hal_support.h ++++ b/dsl_hal_support.h +@@ -49,7 +49,7 @@ + * 04Nov05 0.11.00 CPH Fixed T1413 mode got Zero DS/US rate when DSL_BIT_TMODE is set. + *******************************************************************************/ + +-#include <dsl_hal_api.h> ++#include "dsl_hal_api.h" + + #define virtual2Physical(a) (((int)a)&~0xe0000000) + /* External Function Prototype Declarations */ +--- a/Makefile ++++ b/Makefile +@@ -1,18 +1,9 @@ +-# File: drivers/atm/ti_evm3/Makefile + # +-# Makefile for the Texas Instruments EVM3 ADSL/ATM driver. ++# Makefile for the TIATM device driver. + # +-# +-# Copyright (c) 2000 Texas Instruments Incorporated. +-# Jeff Harrell (jharrell@telogy.com) +-# Viren Balar (vbalar@ti.com) +-# Victor Wells (vwells@telogy.com) +-# +-include $(TOPDIR)/Rules.make +- +- +- +- +- +- + ++CONFIG_SANGAM_ATM=m ++#EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++obj-$(CONFIG_SANGAM_ATM) := tiatm.o ++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -66,7 +66,6 @@ + * 09/18/07 CPH CQ11466 Added EFM Support + *********************************************************************************************/ + +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -74,11 +73,14 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++ ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> ++ + #include "dsl_hal_api.h" + #ifdef AR7_EFM + #include "tn7efm.h" +@@ -90,6 +92,7 @@ + #include "dsl_hal_register.h" + + #ifdef MODULE ++MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver"); + MODULE_AUTHOR ("Zhicheng Tang"); + #endif +@@ -108,9 +111,9 @@ MODULE_AUTHOR ("Zhicheng Tang"); + + /*end of externs */ + +-#ifndef TI_STATIC_ALLOCATIONS +-#define TI_STATIC_ALLOCATIONS +-#endif ++//#ifndef TI_STATIC_ALLOCATIONS ++//#define TI_STATIC_ALLOCATIONS ++//#endif + + #define tn7atm_kfree_skb(x) dev_kfree_skb(x) + +@@ -135,7 +138,7 @@ static int EnableQoS = FALSE; + /* prototypes */ + static int tn7atm_set_can_support_adsl2 (int can); + +-static int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci); ++static int tn7atm_open (struct atm_vcc *vcc); + + void tn7atm_close (struct atm_vcc *vcc); + +@@ -298,13 +301,12 @@ static const struct atmdev_ops tn7atm_op + getsockopt: NULL, + setsockopt: NULL, + send: tn7atm_send, +- sg_send: NULL, + phy_put: NULL, + phy_get: NULL, + change_qos: tn7atm_change_qos, + }; + +-const char drv_proc_root_folder[] = "avalanche/"; ++const char drv_proc_root_folder[] = "avalanche"; + static struct proc_dir_entry *root_proc_dir_entry = NULL; + #define DRV_PROC_MODE 0644 + static int proc_root_already_exists = TRUE; +@@ -626,56 +628,6 @@ static int turbodsl_check_priority_type( + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * +- * Function: int tn7atm_walk_vccs(struct atm_dev *dev, short *vcc, int *vci) +- * +- * Description: retrieve VPI/VCI for connection +- * +- *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static int tn7atm_walk_vccs (struct atm_vcc *vcc, short *vpi, int *vci) +-{ +- struct atm_vcc *walk; +- +- /* +- * find a free VPI +- */ +- if (*vpi == ATM_VPI_ANY) +- { +- +- for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) +- { +- +- if ((walk->vci == *vci) && (walk->vpi == *vpi)) +- { +- (*vpi)++; +- walk = vcc->dev->vccs; +- } +- } +- } +- +- /* +- * find a free VCI +- */ +- if (*vci == ATM_VCI_ANY) +- { +- +- for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; +- walk = walk->next) +- { +- +- if ((walk->vpi = *vpi) && (walk->vci == *vci)) +- { +- *vci = walk->vci + 1; +- walk = vcc->dev->vccs; +- } +- } +- } +- +- return 0; +-} +- +- +-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- * + * Function: int tn7atm_sar_irq(void) + * + * Description: tnetd73xx SAR interrupt. +@@ -766,7 +718,7 @@ static int __init tn7atm_irq_request (st + + priv->sar_irq = LNXINTNUM (ATM_SAR_INT); /* Interrupt line # */ + +- if (request_irq (priv->sar_irq, tn7atm_sar_irq, SA_INTERRUPT, "SAR ", dev)) ++ if (request_irq (priv->sar_irq, tn7atm_sar_irq, IRQF_DISABLED, "SAR ", dev)) + printk ("Could not register tn7atm_sar_irq\n"); + + /* +@@ -777,8 +729,8 @@ static int __init tn7atm_irq_request (st + { + def_sar_inter_pace = os_atoi (ptr); + } +- avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, +- def_sar_inter_pace); ++ /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, ++ def_sar_inter_pace); */ + + + #ifdef AR7_EFM +@@ -790,7 +742,7 @@ static int __init tn7atm_irq_request (st + * Reigster Receive interrupt A + */ + priv->dsl_irq = LNXINTNUM (ATM_DSL_INT); /* Interrupt line # */ +- if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, SA_INTERRUPT, "DSL ", dev)) ++ if (request_irq (priv->dsl_irq, tn7atm_dsl_irq, IRQF_DISABLED, "DSL ", dev)) + printk ("Could not register tn7atm_dsl_irq\n"); + + /***** VRB Tasklet Mode ****/ +@@ -958,11 +910,15 @@ static int __init tn7atm_get_ESI (struct + #define ATM_VBR_RT 5 + #endif + +-int tn7atm_open (struct atm_vcc *vcc, short vpi, int vci) ++int tn7atm_open (struct atm_vcc *vcc) + { + tn7atm_activate_vc_parm_t tn7atm_activate_vc_parm; + int rc; + //int flags; ++ tn7atm_activate_vc_parm.pcr = 0x20000; ++ tn7atm_activate_vc_parm.scr = 0x20000; ++ tn7atm_activate_vc_parm.mbs = 0x20000; ++ tn7atm_activate_vc_parm.cdvt = 10000; + + dgprintf(1, "tn7atm_open()\n"); + +@@ -974,24 +930,18 @@ int tn7atm_open (struct atm_vcc *vcc, sh + return -1; + } + +- MOD_INC_USE_COUNT; ++// MOD_INC_USE_COUNT; + +- /* find a free VPI/VCI */ +- tn7atm_walk_vccs(vcc, &vpi, &vci); +- +- vcc->vpi = vpi; +- vcc->vci = vci; +- +- if ((vci == ATM_VCI_UNSPEC) || (vpi == ATM_VCI_UNSPEC)) ++ if ((vcc->vci == ATM_VCI_UNSPEC) || (vcc->vpi == ATM_VCI_UNSPEC)) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + return -EBUSY; + } + +- tn7atm_activate_vc_parm.vpi = vpi; +- tn7atm_activate_vc_parm.vci = vci; ++ tn7atm_activate_vc_parm.vpi = vcc->vpi; ++ tn7atm_activate_vc_parm.vci = vcc->vci; + +- if ((vpi == CLEAR_EOC_VPI) && (vci == CLEAR_EOC_VCI)) ++ if ((vcc->vpi == CLEAR_EOC_VPI) && (vcc->vci == CLEAR_EOC_VCI)) + { + /* always use (max_dma_chan+1) for clear eoc */ + tn7atm_activate_vc_parm.chan = EOC_DMA_CHAN; +@@ -999,7 +949,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + /* check to see whether clear eoc is opened or not */ + if (tn7atm_activate_vc_parm.priv->lut[tn7atm_activate_vc_parm.chan].inuse) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + printk("tn7atm_open: Clear EOC channel (dmachan=%d) already in use.\n", tn7atm_activate_vc_parm.chan); + return -EBUSY; + } +@@ -1008,7 +958,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + if (rc) + { + printk("tn7atm_open: failed to setup clear_eoc\n"); +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + return -EBUSY; + } + tn7atm_set_lut(tn7atm_activate_vc_parm.priv,vcc, tn7atm_activate_vc_parm.chan); +@@ -1017,17 +967,17 @@ int tn7atm_open (struct atm_vcc *vcc, sh + } + else /* PVC channel setup */ + { +- if ((vpi==REMOTE_MGMT_VPI) && (vci==REMOTE_MGMT_VCI)) ++ if ((vcc->vpi==REMOTE_MGMT_VPI) && (vcc->vci==REMOTE_MGMT_VCI)) + { + tn7atm_activate_vc_parm.chan = 14; /* always use chan 14 for MII PVC-base romote mgmt */ + } + else + { +- rc = tn7atm_lut_find(vpi, vci); ++ rc = tn7atm_lut_find(vcc->vpi, vcc->vci); + /* check to see whether PVC is opened or not */ + if(ATM_NO_DMA_CHAN != rc) + { +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + printk("PVC already opened. dmachan = %d\n", rc); + return -EBUSY; + } +@@ -1059,6 +1009,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + tn7atm_activate_vc_parm.priority = 2; + break; + ++#if 0 + case ATM_VBR: /* Variable Bit Rate-Non RealTime*/ + tn7atm_activate_vc_parm.qos = 1; + tn7atm_activate_vc_parm.priority = 1; +@@ -1080,6 +1031,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + tn7atm_activate_vc_parm.mbs = vcc->qos.txtp.max_pcr; + tn7atm_activate_vc_parm.cdvt = vcc->qos.txtp.max_cdv; + break; ++#endif + + default: + tn7atm_activate_vc_parm.qos = 2; +@@ -1107,7 +1059,7 @@ int tn7atm_open (struct atm_vcc *vcc, sh + if (rc < 0) + { + printk("failed to activate hw channel\n"); +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + tn7atm_lut_clear(vcc, tn7atm_activate_vc_parm.chan); + //spin_unlock_irqrestore(&chan_init_lock, flags); + return -EBUSY; +@@ -1197,7 +1149,7 @@ void tn7atm_close (struct atm_vcc *vcc) + tn7atm_lut_clear (vcc, dmachan); + //spin_unlock_irqrestore (&closeLock, closeFlag); + +- MOD_DEC_USE_COUNT; ++// MOD_DEC_USE_COUNT; + + dgprintf (1, "Leave tn7atm_close\n"); + } +@@ -1630,8 +1582,7 @@ int tn7atm_receive (void *os_dev, int ch + * firewall is on */ + + dgprintf (3, "pushing the skb...\n"); +- +- skb->stamp = vcc->timestamp = xtime; ++ __net_timestamp(skb); + + xdump ((unsigned char *) skb->data, skb->len, 5); + +@@ -1854,8 +1805,7 @@ printk("!!!free atm irq: tn7atm_exit\n") + + kfree (dev->dev_data); + +- // atm_dev_deregister (dev); +- shutdown_atm_dev (dev); ++ atm_dev_deregister (dev); + + /* + * remove proc entries +@@ -2086,9 +2036,6 @@ static int __init tn7atm_detect (void) + * Set up proc entry for atm stats + */ + +- if (tn7atm_xlate_proc_name +- (drv_proc_root_folder, &root_proc_dir_entry, &residual)) +- { + printk ("Creating new root folder %s in the proc for the driver stats \n", + drv_proc_root_folder); + root_proc_dir_entry = proc_mkdir (drv_proc_root_folder, NULL); +@@ -2098,7 +2045,6 @@ static int __init tn7atm_detect (void) + return -ENOMEM; + } + proc_root_already_exists = FALSE; +- } + + + /* +@@ -2731,7 +2677,5 @@ int tn7atm_proc_turbodsl_write(struct fi + return count; + } + +-#ifdef MODULE + module_init (tn7atm_detect); + module_exit (tn7atm_exit); +-#endif /* MODULE */ +--- a/tn7atm.h ++++ b/tn7atm.h +@@ -20,7 +20,8 @@ + //#include "mips_support.h" + #include <linux/list.h> + +-#include <linux/config.h> ++#define MIPS_EXCEPTION_OFFSET 8 ++#define LNXINTNUM(x)((x) + MIPS_EXCEPTION_OFFSET) + + #ifdef CONFIG_MODVERSIONS + #include <linux/modversions.h> +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -102,7 +102,6 @@ + * UR8_MERGE_END CQ11813 + * 09/18/07 CPH CQ11466: Added EFM support. + *********************************************************************************************/ +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -110,8 +109,6 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +@@ -119,6 +116,12 @@ + #include <linux/timer.h> + #include <linux/vmalloc.h> + #include <linux/file.h> ++#include <linux/firmware.h> ++ ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> ++ + /* Modules specific header files */ + #ifdef AR7_EFM + #include "tn7efm.h" +@@ -185,7 +188,7 @@ led_reg_t ledreg[2]; + static struct led_funcs ledreg[2]; + #endif + +-#define DEV_DSLMOD 1 ++#define DEV_DSLMOD CTL_UNNUMBERED + #define MAX_STR_SIZE 256 + #define DSL_MOD_SIZE 256 + +@@ -316,7 +319,7 @@ static PITIDSLHW_T pIhw; + static volatile int bshutdown; + static char info[MAX_STR_SIZE]; + /* Used for DSL Polling enable */ +-static DECLARE_MUTEX_LOCKED (adsl_sem_overlay); ++static struct semaphore adsl_sem_overlay; + + //kthread_t overlay_thread; + /* end of module wide declars */ +@@ -369,6 +372,14 @@ int os_atoih (const char *pstr) + return val; + } + ++int avalanche_request_intr_pacing(int irq_nr, unsigned int blk_num, ++ unsigned int pace_value) ++{ ++ printk("avalanche_request_pacing(%d, %u, %u); // not implemented\n", irq_nr, blk_num, pace_value); ++ return 0; ++} ++ ++ + int os_atoi(const char *pStr) + { + int MulNeg = (*pStr == '-' ? -1 : 1); +@@ -405,39 +416,6 @@ void dprintf (int uDbgLevel, char *szFmt + #endif + } + +-int strcmp(const char *s1, const char *s2) +-{ +- +- int size = strlen(s1); +- +- return(strncmp(s1, s2, size)); +-} +- +-int strncmp(const char *s1, const char *s2, size_t size) +-{ +- int i = 0; +- int max_size = (int)size; +- +- while((s1[i] != 0) && i < max_size) +- { +- if(s2[i] == 0) +- { +- return -1; +- } +- if(s1[i] != s2[i]) +- { +- return 1; +- } +- i++; +- } +- if(s2[i] != 0) +- { +- return 1; +- } +- +- return 0; +-} +- + // * UR8_MERGE_START CQ10640 Jack Zhang + int tn7dsl_dump_dsp_memory(char *input_str) //cph99 + { +@@ -487,144 +465,78 @@ unsigned int shim_osGetCpuFrequency(void + return CpuFrequency; + } + +-int shim_osLoadFWImage(unsigned char *ptr) ++static void avsar_release(struct device *dev) + { +- unsigned int bytesRead; +- mm_segment_t oldfs; +- static struct file *filp; +- unsigned int imageLength=0x5ffff; +- +-#ifdef AR7_EFM +- int dp_alt=0; +- char *ptr1=NULL; +-#ifdef EFM_DEBUG +- char *ptr2=NULL; +- char *ptr3=NULL; +-#endif +- +- if ((ptr1 = prom_getenv("DSL_DP_ALT")) != NULL) +- { +- dp_alt=os_atoi(ptr1); +- if (dp_alt==1) +- { +- filp = filp_open(DSP_DEBUG_FIRMWARE_PATH,00,O_RDONLY); +- if (!IS_ERR(filp)) +- { +- strcpy (DSP_FIRMWARE_PATH, DSP_DEBUG_FIRMWARE_PATH); +- } +- } +-#ifdef EFM_DEBUG +- else if (dp_alt==2) +- { +- if ((ptr2 = prom_getenv("DSL_DP")) != NULL) +- { +- if (!strncmp(ptr2, "DSL_DP", 6)) +- { // indirect naming +- if ((ptr3 = prom_getenv(ptr2)) != NULL) +- filp = filp_open(ptr3,00,O_RDONLY); +- ptr2 = ptr3; // redirect ptr2 to ptr3 +- } +- +- filp = filp_open(ptr2,00,O_RDONLY); +- if (!IS_ERR(filp)) +- { +- strcpy (DSP_FIRMWARE_PATH, ptr2); +- } +- } +- } +- printk("dp_path=%s\n", DSP_FIRMWARE_PATH); +-#endif +- } +-#endif +- +- dgprintf(4, "tn7dsl_read_dsp()\n"); +- +- dgprintf(4,"open file %s\n", DSP_FIRMWARE_PATH); +- +- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY); +- if(IS_ERR(filp)) +- { +- printk("Failed: Could not open DSP binary file\n"); +- return -1; +- } +- +- if (filp->f_dentry != NULL) +- { +- if (filp->f_dentry->d_inode != NULL) +- { +- printk ("DSP binary filesize = %d bytes\n", +- (int) filp->f_dentry->d_inode->i_size); +- imageLength = (unsigned int)filp->f_dentry->d_inode->i_size + 0x200; +- } +- } +- +- if (filp->f_op->read==NULL) +- return -1; /* File(system) doesn't allow reads */ +- +- /* +- * Disable parameter checking +- */ +- oldfs = get_fs(); +- set_fs(KERNEL_DS); +- +- /* +- * Now read bytes from postion "StartPos" +- */ +- filp->f_pos = 0; +- +- bytesRead = filp->f_op->read(filp,ptr,imageLength,&filp->f_pos); +- +- dgprintf(4,"file length = %d\n", bytesRead); +- +- set_fs(oldfs); +- +- /* +- * Close the file +- */ +- fput(filp); +- +- return bytesRead; ++ printk(KERN_DEBUG "avsar firmware released\n"); + } + ++static struct device avsar = { ++ .bus_id = "vlynq", ++ .release = avsar_release, ++}; + +-unsigned int shim_read_overlay_page (void *ptr, unsigned int secOffset, +- unsigned int secLength) ++int shim_osLoadFWImage(unsigned char *ptr) + { +- unsigned int bytesRead; +- mm_segment_t oldfs; +- struct file *filp; +- +- dgprintf(4,"shim_read_overlay_page\n"); +- //dgprintf(4,"sec offset=%d, sec length =%d\n", secOffset, secLength); ++ const struct firmware *fw_entry; ++ size_t size; + +- filp=filp_open(DSP_FIRMWARE_PATH,00,O_RDONLY); +- if(filp ==NULL) +- { +- printk("Failed: Could not open DSP binary file\n"); +- return -1; +- } +- +- if (filp->f_op->read==NULL) +- return -1; /* File(system) doesn't allow reads */ +- +- /* +- * Now read bytes from postion "StartPos" +- */ ++ printk("requesting firmware image \"ar0700xx.bin\"\n"); ++ if(device_register(&avsar) < 0) { ++ printk(KERN_ERR ++ "avsar: device_register fails\n"); ++ return -1; ++ } ++ ++ if (request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) { ++ printk(KERN_ERR ++ "avsar: Firmware not available\n"); ++ device_unregister(&avsar); ++ return -1; ++ } ++ size = fw_entry->size; ++ device_unregister(&avsar); ++ if (size > 0x6ffff) { ++ printk(KERN_ERR ++ "avsar: Firmware too big (%d bytes)\n", size); ++ release_firmware(fw_entry); ++ return -1; ++ } ++ memcpy(ptr, fw_entry->data, size); ++ release_firmware(fw_entry); ++ return size; ++} ++ ++unsigned int shim_read_overlay_page(void *ptr, unsigned int secOffset, unsigned int secLength) ++{ ++ const struct firmware *fw_entry; ++ ++ printk("requesting firmware image \"ar0700xx.bin\"\n"); ++ if (device_register(&avsar) < 0) { ++ printk(KERN_ERR ++ "avsar: device_register fails\n"); ++ return -1; ++ } ++ ++ if (request_firmware(&fw_entry, "ar0700xx.bin", &avsar)) { ++ printk(KERN_ERR ++ "avsar: Firmware not available\n"); ++ device_unregister(&avsar); ++ return -1; ++ } ++ ++ device_unregister(&avsar); ++ if (fw_entry->size > secLength) { ++ printk(KERN_ERR ++ "avsar: Firmware too big (%d bytes)\n", fw_entry->size); ++ release_firmware(fw_entry); ++ return -1; ++ } ++ memcpy(ptr + secOffset, fw_entry->data, secLength); ++ release_firmware(fw_entry); ++ return secLength; ++} + +- if(filp->f_op->llseek) +- filp->f_op->llseek(filp,secOffset, 0); +- oldfs = get_fs(); +- set_fs(KERNEL_DS); +- filp->f_pos = secOffset; +- bytesRead = filp->f_op->read(filp,ptr,secLength,&filp->f_pos); + +- set_fs(oldfs); +- /* +- * Close the file +- */ +- fput(filp); +- return bytesRead; +-} + + int shim_osLoadDebugFWImage(unsigned char *ptr) + { +@@ -3287,6 +3199,7 @@ int tn7dsl_init(void *priv) + int high_precision_selected = 0; + // UR8_MERGE_END CQ11054* + ++ sema_init(&adsl_sem_overlay, 0); + /* + * start dsl + */ +@@ -3665,7 +3578,7 @@ static int dslmod_sysctl(ctl_table *ctl, + */ + if(write) + { +- ret = proc_dostring(ctl, write, filp, buffer, lenp); ++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); + + switch (ctl->ctl_name) + { +@@ -3751,14 +3664,14 @@ static int dslmod_sysctl(ctl_table *ctl, + else + { + len += sprintf(info+len, mod_req); +- ret = proc_dostring(ctl, write, filp, buffer, lenp); ++ ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); + } + return ret; + } + + + ctl_table dslmod_table[] = { +- {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, &dslmod_sysctl} ++ {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string} + , + {0} + }; +@@ -3781,8 +3694,7 @@ void tn7dsl_dslmod_sysctl_register(void) + if (initialized == 1) + return; + +- dslmod_sysctl_header = register_sysctl_table(dslmod_root_table, 1); +- dslmod_root_table->child->de->owner = THIS_MODULE; ++ dslmod_sysctl_header = register_sysctl_table(dslmod_root_table); + + /* + * set the defaults +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -43,7 +43,6 @@ + * 09/18/07 CPH CQ11466: Added EFM support. + *******************************************************************************/ + +-#include <linux/config.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/init.h> +@@ -51,12 +50,13 @@ + #include <linux/delay.h> + #include <linux/spinlock.h> + #include <linux/smp_lock.h> +-#include <asm/io.h> +-#include <asm/mips-boards/prom.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> + ++#include <asm/io.h> ++#include <asm/ar7/ar7.h> ++#include <asm/ar7/prom.h> + + #define _CPHAL_AAL5 + #define _CPHAL_SAR diff --git a/package/system/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch b/package/system/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch new file mode 100644 index 0000000000..1122457691 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/110-interrupt_fix.patch @@ -0,0 +1,37 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -633,7 +633,7 @@ static int turbodsl_check_priority_type( + * Description: tnetd73xx SAR interrupt. + * + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static void tn7atm_sar_irq (int irq, void *voiddev, struct pt_regs *regs) ++static irqreturn_t tn7atm_sar_irq (int irq, void *voiddev) + { + struct atm_dev *atmdev; + Tn7AtmPrivate *priv; +@@ -660,6 +660,7 @@ static void tn7atm_sar_irq (int irq, voi + #ifdef TIATM_INST_SUPP + psp_trace_par (ATM_DRV_SAR_ISR_EXIT, retval); + #endif ++ return IRQ_HANDLED; + } + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +@@ -669,7 +670,7 @@ static void tn7atm_sar_irq (int irq, voi + * Description: tnetd73xx DSL interrupt. + * + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +-static void tn7atm_dsl_irq (int irq, void *voiddev, struct pt_regs *regs) ++static irqreturn_t tn7atm_dsl_irq (int irq, void *voiddev) + { + struct atm_dev *atmdev; + Tn7AtmPrivate *priv; +@@ -691,6 +692,8 @@ static void tn7atm_dsl_irq (int irq, voi + #ifdef TIATM_INST_SUPP + psp_trace_par (ATM_DRV_DSL_ISR_EXIT, retval); + #endif ++ ++ return IRQ_HANDLED; + } + + /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/package/system/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch b/package/system/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch new file mode 100644 index 0000000000..e9d99dff42 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/120-no_dumb_inline.patch @@ -0,0 +1,11 @@ +--- a/tn7api.h ++++ b/tn7api.h +@@ -118,7 +118,7 @@ int tn7dsl_proc_dbgmsg_write(struct file + int tn7dsl_proc_dbgmsg_read(char* buf, char **start, off_t offset, int count,int *eof, void *data); + #endif + //UR8_MERGE_END CQ11813 +-inline int tn7dsl_handle_interrupt(void); ++int tn7dsl_handle_interrupt(void); + + void tn7dsl_dslmod_sysctl_register(void); + void tn7dsl_dslmod_sysctl_unregister(void); diff --git a/package/system/ar7-atm/patches-D7.05.01.00/130-powercutback.patch b/package/system/ar7-atm/patches-D7.05.01.00/130-powercutback.patch new file mode 100644 index 0000000000..415486482e --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/130-powercutback.patch @@ -0,0 +1,44 @@ +--- a/dsl_hal_advcfg.c ++++ b/dsl_hal_advcfg.c +@@ -36,9 +36,9 @@ + * 05Jul05 0.00.09 CPH CQ9775: Change dslhal_advcfg_configDsTones input parameters & support for ADSL2+ + * 24Jul05 0.00.10 CPH Fixed comments in dslhal_advcfg_configDsTones function header + *******************************************************************************/ +-#include <dev_host_interface.h> +-#include <dsl_hal_register.h> +-#include <dsl_hal_support.h> ++#include "dev_host_interface.h" ++#include "dsl_hal_register.h" ++#include "dsl_hal_support.h" + + /*****************************************************************************/ + /* ACT API functions -- To be moved into their own independent module --RamP */ +--- a/Makefile ++++ b/Makefile +@@ -4,6 +4,7 @@ + + CONFIG_SANGAM_ATM=m + #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT +-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL + obj-$(CONFIG_SANGAM_ATM) := tiatm.o +-tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o ++tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -3053,6 +3053,14 @@ static int tn7dsl_set_dsl(void) + dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr)); + } + ++ // set powercutback ++ ptr = NULL; ++ ptr = prom_getenv("powercutback"); ++ if(ptr) ++ { ++ dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr)); ++ } ++ + // trellis + ptr = NULL; + ptr = prom_getenv("trellis"); diff --git a/package/system/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch b/package/system/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch new file mode 100644 index 0000000000..3873827afc --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/140-debug_mode.patch @@ -0,0 +1,16 @@ +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -125,10 +125,10 @@ enum + //09/05/07: cph, move to tn7atm.h + // #define RESERVED_OAM_CHANNEL 15 + +-#define AAL5_PARM "id=aal5, base = 0x03000000, offset = 0, int_line=15, ch0=[RxBufSize=1522; RxNumBuffers = 32; RxServiceMax = 50; TxServiceMax=50; TxNumBuffers=32; CpcsUU=0x5aa5; TxVc_CellRate=0x3000; TxVc_AtmHeader=0x00000640]" +-#define SAR_PARM "id=sar,base = 0x03000000, reset_bit = 9, offset = 0; UniNni = 0, PdspEnable = 1" ++#define CH0_PARM "RxBufSize=1522, RxNumBuffers=32, RxServiceMax=50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640" ++#define AAL5_PARM "id=aal5, base=0x03000000, offset=0, int_line=15, ch0=[" CH0_PARM "]" ++#define SAR_PARM "id=sar, base=0x03000000, reset_bit=9, offset=0; UniNni=0, PdspEnable=1, Debug=0xFFFFFFFF" + #define RESET_PARM "id=ResetControl, base=0xA8611600" +-#define CH0_PARM "RxBufSize=1522, RxNumBuffers = 32, RxServiceMax = 50, TxServiceMax=50, TxNumBuffers=32, CpcsUU=0x5aa5, TxVc_CellRate=0x3000, TxVc_AtmHeader=0x00000640" + + #define MAX_PVC_TABLE_ENTRY 16 + diff --git a/package/system/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch b/package/system/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch new file mode 100644 index 0000000000..97b8cecdd9 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/150-tasklet_mode.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -5,6 +5,7 @@ + CONFIG_SANGAM_ATM=m + #EXTRA_CFLAGS += -DEL -I. -DPOST_SILICON -DCOMMON_NSP -DCONFIG_LED_MODULE -DDEREGISTER_LED -DNO_ACT + #EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -DNO_ACT -D__NO__VOICE_PATCH__ -DEL +-EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL ++#EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL ++EXTRA_CFLAGS += -DEL -I$(PWD) -DPOST_SILICON -DCOMMON_NSP -D__NO__VOICE_PATCH__ -DEL -DCPATM_TASKLET_MODE + obj-$(CONFIG_SANGAM_ATM) := tiatm.o + tiatm-objs += cpsar.o aal5sar.o tn7sar.o tn7atm.o tn7dsl.o dsl_hal_api.o dsl_hal_support.o dsl_hal_advcfg.o diff --git a/package/system/ar7-atm/patches-D7.05.01.00/160-module-params.patch b/package/system/ar7-atm/patches-D7.05.01.00/160-module-params.patch new file mode 100644 index 0000000000..75a41d1e36 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/160-module-params.patch @@ -0,0 +1,675 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -95,6 +95,146 @@ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Tnetd73xx ATM Device Driver"); + MODULE_AUTHOR ("Zhicheng Tang"); ++ ++int mp_sar_ipacemax = -1; ++module_param_named(ipacemax, mp_sar_ipacemax, int, 0); ++MODULE_PARM_DESC(ipacemax, "Interrupt pacing"); ++ ++char *mp_macc = NULL; ++module_param_named(macc, mp_macc, charp, 0); ++MODULE_PARM_DESC(macc, "MAC address"); ++ ++int mp_dsp_noboost = -1; ++module_param_named(dsp_noboost, mp_dsp_noboost, int, 0); ++MODULE_PARM_DESC(dsp_noboost, "Suppress DSP frequency boost"); ++ ++int mp_dsp_freq = -1; ++module_param_named(dsp_freq, mp_dsp_freq, int, 0); ++MODULE_PARM_DESC(dsp_freq, "Frequency to boost the DSP to"); ++ ++char *mp_featctl0 = NULL; ++module_param_named(featctl0, mp_featctl0, charp, 0); ++MODULE_PARM_DESC(featctl0, "DSL feature control 0"); ++ ++char *mp_featctl1 = NULL; ++module_param_named(featctl1, mp_featctl1, charp, 0); ++MODULE_PARM_DESC(featctl1, "DSL feature control 1"); ++ ++char *mp_phyctl0 = NULL; ++module_param_named(phyctl0, mp_phyctl0, charp, 0); ++MODULE_PARM_DESC(phyctl0, "DSL PHY control 0"); ++ ++char *mp_phyctl1 = NULL; ++module_param_named(phyctl1, mp_phyctl1, charp, 0); ++MODULE_PARM_DESC(phyctl1, "DSL PHY control 1"); ++ ++int mp_turbodsl = -1; ++module_param_named(turbodsl, mp_turbodsl, int, 0); ++MODULE_PARM_DESC(turbodsl, "Enable TurboDSL"); ++ ++int mp_sar_rxbuf = -1; ++module_param_named(sar_rxbuf, mp_sar_rxbuf, int, 0); ++MODULE_PARM_DESC(sar_rxbuf, "SAR RxBuf size"); ++ ++int mp_sar_rxmax = -1; ++module_param_named(sar_rxmax, mp_sar_rxmax, int, 0); ++MODULE_PARM_DESC(sar_rxmax, "SAR RxMax size"); ++ ++int mp_sar_txbuf = -1; ++module_param_named(sar_txbuf, mp_sar_txbuf, int, 0); ++MODULE_PARM_DESC(sar_txbuf, "SAR TxBuf size"); ++ ++int mp_sar_txmax = -1; ++module_param_named(sar_txmax, mp_sar_txmax, int, 0); ++MODULE_PARM_DESC(sar_txmax, "SAR TxMax size"); ++ ++char *mp_modulation = NULL; ++module_param_named(modulation, mp_modulation, charp, 0); ++MODULE_PARM_DESC(modulation, "Modulation"); ++ ++int mp_fine_gain_control = -1; ++module_param_named(fine_gain_control, mp_fine_gain_control, int, 0); ++MODULE_PARM_DESC(fine_gain_control, "Fine gain control"); ++ ++int mp_fine_gain_value = -1; ++module_param_named(fine_gain_value, mp_fine_gain_value, int, 0); ++MODULE_PARM_DESC(fine_gain_value, "Fine gain value"); ++ ++int mp_enable_margin_retrain = -1; ++module_param_named(enable_margin_retrain, mp_enable_margin_retrain, int, 0); ++MODULE_PARM_DESC(enable_margin_retrain, "Enable margin retrain"); ++ ++int mp_margin_threshold = -1; ++module_param_named(margin_threshold, mp_margin_threshold, int, 0); ++MODULE_PARM_DESC(margin_threshold, "Margin retrain treshold"); ++ ++int mp_enable_rate_adapt = -1; ++module_param_named(enable_rate_adapt, mp_enable_rate_adapt, int, 0); ++MODULE_PARM_DESC(enable_rate_adapt, "Enable rate adaption"); ++ ++int mp_powercutback = -1; ++module_param_named(powercutback, mp_powercutback, int, 0); ++MODULE_PARM_DESC(powercutback, "Enable / disable powercutback"); ++ ++int mp_trellis = -1; ++module_param_named(trellis, mp_trellis, int, 0); ++MODULE_PARM_DESC(trellis, "Enable / disable trellis coding"); ++ ++int mp_bitswap = -1; ++module_param_named(bitswap, mp_bitswap, int, 0); ++MODULE_PARM_DESC(bitswap, "Enable / disable bitswap"); ++ ++int mp_maximum_bits_per_carrier = -1; ++module_param_named(maximum_bits_per_carrier, mp_maximum_bits_per_carrier, int, 0); ++MODULE_PARM_DESC(maximum_bits_per_carrier, "Maximum bits per carrier"); ++ ++int mp_maximum_interleave_depth = -1; ++module_param_named(maximum_interleave_depth, mp_maximum_interleave_depth, int, 0); ++MODULE_PARM_DESC(maximum_interleave_depth, "Maximum interleave depth"); ++ ++int mp_pair_selection = -1; ++module_param_named(pair_selection, mp_pair_selection, int, 0); ++MODULE_PARM_DESC(pair_selection, "Pair selection"); ++ ++int mp_dgas_polarity = -1; ++module_param_named(dgas_polarity, mp_dgas_polarity, int, 0); ++MODULE_PARM_DESC(dgas_polarity, "DGAS polarity"); ++ ++int mp_los_alarm = -1; ++module_param_named(los_alarm, mp_los_alarm, int, 0); ++MODULE_PARM_DESC(los_alarm, "LOS alarm"); ++ ++char *mp_eoc_vendor_id = NULL; ++module_param_named(eoc_vendor_id, mp_eoc_vendor_id, charp, 0); ++MODULE_PARM_DESC(eoc_vendor_id, "EOC vendor id"); ++ ++int mp_eoc_vendor_revision = -1; ++module_param_named(eoc_vendor_revision, mp_eoc_vendor_revision, int, 0); ++MODULE_PARM_DESC(eoc_vendor_revision, "EOC vendor revision"); ++ ++char *mp_eoc_vendor_serialnum = NULL; ++module_param_named(eoc_vendor_serialnum, mp_eoc_vendor_serialnum, charp, 0); ++MODULE_PARM_DESC(eoc_vendor_serialnum, "EOC vendor serial number"); ++ ++char *mp_invntry_vernum = NULL; ++module_param_named(invntry_vernum, mp_invntry_vernum, charp, 0); ++MODULE_PARM_DESC(invntry_vernum, "Inventory revision number"); ++ ++int mp_dsl_bit_tmode = -1; ++module_param_named(dsl_bit_tmode, mp_dsl_bit_tmode, int, 0); ++MODULE_PARM_DESC(dsl_bit_tmode, "DSL bit training mode"); ++ ++int mp_high_precision = -1; ++module_param_named(high_precision, mp_high_precision, int, 0); ++MODULE_PARM_DESC(high_precision, "High precision"); ++ ++int mp_autopvc_enable = -1; ++module_param_named(autopvc_enable, mp_autopvc_enable, int, 0); ++MODULE_PARM_DESC(autopvc_enable, "Enable / disable automatic PVC"); ++ ++int mp_oam_lb_timeout = -1; ++module_param_named(oam_lb_timeout, mp_oam_lb_timeout, int, 0); ++MODULE_PARM_DESC(oam_lb_timeout, "OAM LB timeout"); + #endif + + #ifndef TRUE +@@ -728,9 +868,9 @@ + * interrupt pacing + */ + ptr = prom_getenv ("sar_ipacemax"); +- if (ptr) ++ if (ptr || mp_sar_ipacemax != -1) + { +- def_sar_inter_pace = os_atoi (ptr); ++ def_sar_inter_pace = mp_sar_ipacemax == -1 ? os_atoi (ptr) : mp_sar_ipacemax; + } + /* avalanche_request_pacing (priv->sar_irq, ATM_SAR_INT_PACING_BLOCK_NUM, + def_sar_inter_pace); */ +@@ -878,9 +1018,18 @@ + { + int i; + char esi_addr[ESI_LEN] = { 0x00, 0x00, 0x11, 0x22, 0x33, 0x44 }; +- char *esiaddr_str = NULL; ++ char *esiaddr_str = mp_macc; + +- esiaddr_str = prom_getenv ("macc"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macdsl"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macc"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("HWA_1"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("macb"); ++ if (esiaddr_str == NULL) ++ esiaddr_str = prom_getenv ("maca"); + + if (!esiaddr_str) + { +@@ -2139,15 +2288,15 @@ + //UR8_MERGE_END CQ10450* + + cp = prom_getenv ("dsp_noboost"); +- if (cp) ++ if (cp || mp_dsp_noboost != -1) + { +- dsp_noboost = os_atoi (cp); ++ dsp_noboost = mp_dsp_noboost == -1 ? os_atoi (cp) : mp_dsp_noboost; + } + + cp = (char *) prom_getenv ("dsp_freq"); +- if (cp) ++ if (cp || mp_dsp_freq != -1) + { +- dspfreq = os_atoi (cp); ++ dspfreq = mp_dsp_freq == -1 ? os_atoi (cp) : mp_dsp_freq; + if (dspfreq == 250) + { + boostDsp = 1; +@@ -2396,15 +2545,17 @@ + // Inter-Op DSL phy Control + // Note the setting of _dsl_Feature_0 and _dsl_Feature_1 must before + // dslhal_api_dslStartup (in tn7dsl_init()). +- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL) ++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_0")) != NULL || mp_featctl0 != NULL) + { +- _dsl_Feature_0 = os_atoih (ptr); ++ if (mp_featctl0 != NULL) ptr = mp_featctl0; ++ _dsl_Feature_0 = os_atoh (ptr); + _dsl_Feature_0_defined = 1; + } + +- if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL) ++ if ((ptr = prom_getenv ("DSL_FEATURE_CNTL_1")) != NULL || mp_featctl1 != NULL) + { +- _dsl_Feature_1 = os_atoih (ptr); ++ if (mp_featctl1 != NULL) ptr = mp_featctl1; ++ _dsl_Feature_1 = os_atoh (ptr); + _dsl_Feature_1_defined = 1; + } + +@@ -2412,15 +2563,17 @@ + // DSL phy Feature Control + // Note the setting of _dsl_PhyControl_0 and _dsl_PhyControl_1 must before + // dslhal_api_dslStartup (in tn7dsl_init()). +- if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL) ++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_0")) != NULL || mp_phyctl0 != NULL) + { +- _dsl_PhyControl_0 = os_atoih (ptr); ++ if (mp_phyctl0 != NULL) ptr = mp_phyctl0; ++ _dsl_PhyControl_0 = os_atoh (ptr); + _dsl_PhyControl_0_defined = 1; + } + +- if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL) ++ if ((ptr = prom_getenv ("DSL_PHY_CNTL_1")) != NULL || mp_phyctl1 != NULL) + { +- _dsl_PhyControl_1 = os_atoih (ptr); ++ if (mp_phyctl1 != NULL) ptr = mp_phyctl1; ++ _dsl_PhyControl_1 = os_atoh (ptr); + _dsl_PhyControl_1_defined = 1; + } + +@@ -2440,12 +2593,12 @@ + // read config for turbo dsl + + ptr = prom_getenv ("TurboDSL"); +- if (ptr) ++ if (ptr || mp_turbodsl != -1) + { + #if 1 //[KT] + bTurboDsl = os_atoi (ptr); + #else +- priv->bTurboDsl = os_atoi (ptr); ++ priv->bTurboDsl = mp_turbodsl == -1 ? os_atoi (ptr) : mp_turbodsl; + #endif + } + else +@@ -2459,33 +2612,33 @@ + priv->sarRxBuf = RX_BUFFER_NUM; + ptr = NULL; + ptr = prom_getenv ("SarRxBuf"); +- if (ptr) ++ if (ptr || mp_sar_rxbuf != -1) + { +- priv->sarRxBuf = os_atoi (ptr); ++ priv->sarRxBuf = mp_sar_rxbuf == -1 ? os_atoi (ptr) : mp_sar_rxbuf; + } + + priv->sarRxMax = RX_SERVICE_MAX; + ptr = NULL; + ptr = prom_getenv ("SarRxMax"); +- if (ptr) ++ if (ptr || mp_sar_rxmax != -1) + { +- priv->sarRxMax = os_atoi (ptr); ++ priv->sarRxMax = mp_sar_rxmax == -1 ? os_atoi (ptr) : mp_sar_rxmax; + } + + priv->sarTxBuf = TX_BUFFER_NUM; + ptr = NULL; + ptr = prom_getenv ("SarTxBuf"); +- if (ptr) ++ if (ptr || mp_sar_txbuf != -1) + { +- priv->sarTxBuf = os_atoi (ptr); ++ priv->sarTxBuf = mp_sar_txbuf == -1 ? os_atoi (ptr) : mp_sar_txbuf; + } + + priv->sarTxMax = TX_SERVICE_MAX; + ptr = NULL; + ptr = prom_getenv ("SarTxMax"); +- if (ptr) ++ if (ptr || mp_sar_txmax != -1) + { +- priv->sarTxMax = os_atoi (ptr); ++ priv->sarTxMax = mp_sar_txmax == -1 ? os_atoi (ptr) : mp_sar_txmax; + } + + #ifdef AR7_EFM +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -148,6 +148,27 @@ + #define NEW_TRAINING_VAL_T1413 128 + #define NEW_TRAINING_VAL_MMODE 255 + ++extern char *mp_modulation; ++extern int mp_fine_gain_control; ++extern int mp_fine_gain_value; ++extern int mp_enable_margin_retrain; ++extern int mp_margin_threshold; ++extern int mp_enable_rate_adapt; ++extern int mp_powercutback; ++extern int mp_trellis; ++extern int mp_bitswap; ++extern int mp_maximum_bits_per_carrier; ++extern int mp_maximum_interleave_depth; ++extern int mp_pair_selection; ++extern int mp_dgas_polarity; ++extern int mp_los_alarm; ++extern char *mp_eoc_vendor_id; ++extern int mp_eoc_vendor_revision; ++extern char *mp_eoc_vendor_serialnum; ++extern char *mp_invntry_vernum; ++extern int mp_dsl_bit_tmode; ++extern int mp_high_precision; ++ + int testflag1 = 0; + extern int __guDbgLevel; + extern sar_stat_t sarStat; +@@ -2933,24 +2954,24 @@ static int tn7dsl_set_dsl(void) + (unsigned char *) &oamFeature, 4); + + ptr = prom_getenv("DSL_FEATURE_CNTL_0"); +- if(!ptr) +- prom_setenv("DSL_FEATURE_CNTL_0", "0x00004000"); ++ //if(!ptr) ++ //prom_setenv("DSL_FEATURE_CNTL_0", "0x00004000"); + + ptr = prom_getenv("DSL_FEATURE_CNTL_1"); +- if(!ptr) +- prom_setenv("DSL_FEATURE_CNTL_1", "0x00000000"); ++ //if(!ptr) ++ //prom_setenv("DSL_FEATURE_CNTL_1", "0x00000000"); + + ptr = prom_getenv("DSL_PHY_CNTL_0"); +- if(!ptr) +- prom_setenv("DSL_PHY_CNTL_0", "0x00000400"); ++ //if(!ptr) ++ //prom_setenv("DSL_PHY_CNTL_0", "0x00000400"); + + ptr = prom_getenv("enable_margin_retrain"); +- if(!ptr) +- prom_setenv("enable_margin_retrain", "0"); ++ //if(!ptr) ++ //prom_setenv("enable_margin_retrain", "0"); + + ptr = prom_getenv("modulation"); +- if(!ptr) +- prom_setenv("modulation", "0xbf"); ++ //if(!ptr) ++ //prom_setenv("modulation", "0xbf"); + + #define EOC_VENDOR_ID "4200534153000000" + #define EOC_VENDOR_REVISION "FW370090708b1_55" +@@ -2959,25 +2980,25 @@ static int tn7dsl_set_dsl(void) + ptr = prom_getenv("eoc_vendor_id"); + if(!ptr || strcmp(ptr,EOC_VENDOR_ID) != 0 || strlen(ptr) != strlen(EOC_VENDOR_ID)) + { +- if(ptr) +- prom_unsetenv("eoc_vendor_id"); +- prom_setenv("eoc_vendor_id",EOC_VENDOR_ID); ++ //if(ptr) ++ //prom_unsetenv("eoc_vendor_id"); ++ //prom_setenv("eoc_vendor_id",EOC_VENDOR_ID); + } + + ptr = prom_getenv("eoc_vendor_revision"); + if(!ptr || strcmp(ptr,EOC_VENDOR_REVISION) != 0 || strlen(ptr) != strlen(EOC_VENDOR_REVISION)) + { +- if(ptr) +- prom_unsetenv("eoc_vendor_revision"); +- prom_setenv("eoc_vendor_revision",EOC_VENDOR_REVISION); ++ //if(ptr) ++ //prom_unsetenv("eoc_vendor_revision"); ++ //prom_setenv("eoc_vendor_revision",EOC_VENDOR_REVISION); + } + + ptr = prom_getenv("eoc_vendor_serialnum"); + if(!ptr || strcmp(ptr,EOC_VENDOR_SERIALNUM) != 0 || strlen(ptr) != strlen(EOC_VENDOR_SERIALNUM)) + { +- if(ptr) +- prom_unsetenv("eoc_vendor_serialnum"); +- prom_setenv("eoc_vendor_serialnum",EOC_VENDOR_SERIALNUM); ++ //if(ptr) ++ // prom_unsetenv("eoc_vendor_serialnum"); ++ //prom_setenv("eoc_vendor_serialnum",EOC_VENDOR_SERIALNUM); + } + + /* Do only if we are in the new Base PSP 7.4.*/ +@@ -2994,92 +3015,88 @@ static int tn7dsl_set_dsl(void) + we clear the modulation environment variable, as this could potentially + not have the same meaning in the new mode. + */ +- prom_unsetenv("modulation"); +- prom_setenv("DSL_UPG_DONE", "1"); ++ //prom_unsetenv("modulation"); ++ //prom_setenv("DSL_UPG_DONE", "1"); + } + } + #endif + + // modulation + ptr = prom_getenv("modulation"); +- if (ptr) ++ if (ptr || mp_modulation != NULL) + { +- tn7dsl_set_modulation(ptr, FALSE); ++ tn7dsl_set_modulation(mp_modulation == NULL ? ptr : mp_modulation, FALSE); + } + + // Fine Gains + ptr = prom_getenv("fine_gain_control"); +- if (ptr) ++ if (ptr || mp_fine_gain_control != -1) + { +- value = os_atoi(ptr); ++ value = mp_fine_gain_control == -1 ? os_atoi(ptr) : mp_fine_gain_control; + tn7dsl_ctrl_fineGain(value); + } + ptr = NULL; + ptr = prom_getenv("fine_gain_value"); +- if(ptr) +- tn7dsl_set_fineGainValue(os_atoh(ptr)); ++ if(ptr || mp_fine_gain_value != -1) ++ tn7dsl_set_fineGainValue(mp_fine_gain_value == -1 ? os_atoh(ptr) : mp_fine_gain_value); + + // margin retrain + ptr = NULL; + ptr = prom_getenv("enable_margin_retrain"); +- if(ptr) ++ value = mp_enable_margin_retrain == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_enable_margin_retrain; ++ ++ if (value == 1) + { +- value = os_atoi(ptr); +- if(value == 1) ++ dslhal_api_setMarginMonitorFlags(pIhw, 0, 1); ++ bMarginRetrainEnable = 1; ++ //printk("enable showtime margin monitor.\n"); ++ ++ ptr = NULL; ++ ptr = prom_getenv("margin_threshold"); ++ value = mp_margin_threshold == -1 ? (ptr ? os_atoi(ptr) : 0) : mp_margin_threshold; ++ ++ if(value >= 0) + { +- dslhal_api_setMarginMonitorFlags(pIhw, 0, 1); +- bMarginRetrainEnable = 1; +- //printk("enable showtime margin monitor.\n"); +- ptr = NULL; +- ptr = prom_getenv("margin_threshold"); +- if(ptr) +- { +- value = os_atoi(ptr); +- //printk("Set margin threshold to %d x 0.5 db\n",value); +- if(value >= 0) +- { +- dslhal_api_setMarginThreshold(pIhw, value); +- bMarginThConfig=1; +- } +- } ++ dslhal_api_setMarginThreshold(pIhw, value); ++ bMarginThConfig=1; + } + } + + // rate adapt + ptr = NULL; + ptr = prom_getenv("enable_rate_adapt"); +- if(ptr) ++ if(ptr || mp_enable_rate_adapt != -1) + { +- dslhal_api_setRateAdaptFlag(pIhw, os_atoi(ptr)); ++ dslhal_api_setRateAdaptFlag(pIhw, mp_enable_rate_adapt == -1 ? os_atoi(ptr) : mp_enable_rate_adapt); + } + + // set powercutback + ptr = NULL; + ptr = prom_getenv("powercutback"); +- if(ptr) ++ if(ptr || mp_powercutback != -1) + { +- dslhal_advcfg_onOffPcb(pIhw, os_atoi(ptr)); ++ dslhal_advcfg_onOffPcb(pIhw, mp_powercutback == -1 ? os_atoi(ptr) : mp_powercutback); + } + + // trellis + ptr = NULL; + ptr = prom_getenv("trellis"); +- if(ptr) ++ if(ptr || mp_trellis != -1) + { +- dslhal_api_setTrellisFlag(pIhw, os_atoi(ptr)); +- trellis = os_atoi(ptr); ++ trellis = mp_trellis == -1 ? os_atoi(ptr) : mp_trellis; ++ dslhal_api_setTrellisFlag(pIhw, trellis); + //printk("trellis=%d\n"); + } + + // bitswap + ptr = NULL; + ptr = prom_getenv("bitswap"); +- if(ptr) ++ if(ptr || mp_bitswap != -1) + { + int offset[2] = {33, 0}; + unsigned int bitswap; + +- bitswap = os_atoi(ptr); ++ bitswap = mp_bitswap == -1 ? os_atoi(ptr) : mp_bitswap; + + tn7dsl_generic_read(2, offset); + dslReg &= dslhal_support_byteSwap32(0xFFFFFF00); +@@ -3097,46 +3114,47 @@ static int tn7dsl_set_dsl(void) + // maximum bits per carrier + ptr = NULL; + ptr = prom_getenv("maximum_bits_per_carrier"); +- if(ptr) ++ if(ptr || mp_maximum_bits_per_carrier != -1) + { +- dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, os_atoi(ptr)); ++ dslhal_api_setMaxBitsPerCarrierUpstream(pIhw, mp_maximum_bits_per_carrier == -1 ? os_atoi(ptr) : mp_maximum_bits_per_carrier); + } + + // maximum interleave depth + ptr = NULL; + ptr = prom_getenv("maximum_interleave_depth"); +- if(ptr) ++ if(ptr || mp_maximum_interleave_depth != -1) + { +- dslhal_api_setMaxInterleaverDepth(pIhw, os_atoi(ptr)); ++ dslhal_api_setMaxInterleaverDepth(pIhw, mp_maximum_interleave_depth == -1 ? os_atoi(ptr) : mp_maximum_interleave_depth); + } + + // inner and outer pairs + ptr = NULL; + ptr = prom_getenv("pair_selection"); +- if(ptr) ++ if(ptr || mp_pair_selection != -1) + { +- dslhal_api_selectInnerOuterPair(pIhw, os_atoi(ptr)); ++ dslhal_api_selectInnerOuterPair(pIhw, mp_pair_selection == -1 ? os_atoi(ptr) : mp_pair_selection); + } + + ptr = NULL; + ptr = prom_getenv("dgas_polarity"); +- if(ptr) ++ if(ptr || mp_dgas_polarity != -1) + { + dslhal_api_configureDgaspLpr(pIhw, 1, 1); +- dslhal_api_configureDgaspLpr(pIhw, 0, os_atoi(ptr)); ++ dslhal_api_configureDgaspLpr(pIhw, 0, mp_dgas_polarity == -1 ? os_atoi(ptr) : mp_dgas_polarity); + } + + ptr = NULL; + ptr = prom_getenv("los_alarm"); +- if(ptr) ++ if(ptr || mp_los_alarm != -1) + { +- dslhal_api_disableLosAlarm(pIhw, os_atoi(ptr)); ++ dslhal_api_disableLosAlarm(pIhw, mp_los_alarm == -1 ? os_atoi(ptr) : mp_los_alarm); + } + + ptr = NULL; + ptr = prom_getenv("eoc_vendor_id"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_id != NULL) + { ++ ptr = mp_eoc_vendor_id == NULL ? ptr : mp_eoc_vendor_id; + for(i=0;i<8;i++) + { + tmp[0]=ptr[i*2]; +@@ -3161,26 +3179,26 @@ static int tn7dsl_set_dsl(void) + } + ptr = NULL; + ptr = prom_getenv("eoc_vendor_revision"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_revision != -1) + { +- value = os_atoi(ptr); ++ value = mp_eoc_vendor_revision == -1 ? os_atoi(ptr) : mp_eoc_vendor_revision; + //printk("eoc rev=%d\n", os_atoi(ptr)); + dslhal_api_setEocRevisionNumber(pIhw, (char *)&value); + + } + ptr = NULL; + ptr = prom_getenv("eoc_vendor_serialnum"); +- if(ptr) ++ if(ptr || mp_eoc_vendor_serialnum != NULL) + { +- dslhal_api_setEocSerialNumber(pIhw, ptr); ++ dslhal_api_setEocSerialNumber(pIhw, mp_eoc_vendor_serialnum == NULL ? ptr : mp_eoc_vendor_serialnum); + } + + // CQ10037 Added invntry_vernum environment variable to be able to set version number in ADSL2, ADSL2+ modes. + ptr = NULL; + ptr = prom_getenv("invntry_vernum"); +- if(ptr) ++ if(ptr || mp_invntry_vernum != NULL) + { +- dslhal_api_setEocRevisionNumber(pIhw, ptr); ++ dslhal_api_setEocRevisionNumber(pIhw, mp_invntry_vernum == NULL ? ptr : mp_invntry_vernum); + } + + return 0; +@@ -3225,7 +3243,7 @@ int tn7dsl_init(void *priv) + * backward compatibility. + */ + cp = prom_getenv("DSL_BIT_TMODE"); +- if (cp) ++ if (cp || mp_dsl_bit_tmode != -1) + { + printk("%s : env var DSL_BIT_TMODE is set\n", __FUNCTION__); + /* +@@ -3254,9 +3272,9 @@ int tn7dsl_init(void *priv) + + // UR8_MERGE_START CQ11054 Jack Zhang + cp = prom_getenv("high_precision"); +- if (cp) ++ if (cp || mp_high_precision != -1) + { +- high_precision_selected = os_atoi(cp); ++ high_precision_selected = mp_high_precision == -1 ? os_atoi(cp) : mp_high_precision; + } + if ( high_precision_selected) + { +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -76,6 +76,8 @@ typedef void OS_SETUP; + #include "tn7atm.h" + #include "tn7api.h" + ++extern int mp_oam_lb_timeout; ++extern int mp_autopvc_enable; + + /* PDSP Firmware files */ + #include "tnetd7300_sar_firm.h" +@@ -932,9 +934,9 @@ int tn7sar_setup_oam_channel(Tn7AtmPriva + pHalDev = (HAL_DEVICE *)priv->pSarHalDev; + + pauto_pvc = prom_getenv("autopvc_enable"); +- if(pauto_pvc) //CQ10273 ++ if(pauto_pvc || mp_autopvc_enable != -1) //CQ10273 + { +- auto_pvc =tn7sar_strtoul(pauto_pvc, NULL, 10); ++ auto_pvc = mp_autopvc_enable == -1 ? tn7sar_strtoul(pauto_pvc, NULL, 10) : mp_autopvc_enable; + } + + memset(&chInfo, 0xff, sizeof(chInfo)); +@@ -1133,9 +1135,9 @@ int tn7sar_init(struct atm_dev *dev, Tn7 + + /* read in oam lb timeout value */ + pLbTimeout = prom_getenv("oam_lb_timeout"); +- if(pLbTimeout) ++ if(pLbTimeout || mp_oam_lb_timeout != -1) + { +- lbTimeout =tn7sar_strtoul(pLbTimeout, NULL, 10); ++ lbTimeout = mp_oam_lb_timeout == -1 ? tn7sar_strtoul(pLbTimeout, NULL, 10) : mp_oam_lb_timeout; + oamLbTimeout = lbTimeout; + pHalFunc->Control(pHalDev,"OamLbTimeout", "Set", &lbTimeout); + } diff --git a/package/system/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch b/package/system/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch new file mode 100644 index 0000000000..6692f40f6a --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/170-bus_id_removal.patch @@ -0,0 +1,30 @@ +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -117,6 +117,7 @@ + #include <linux/vmalloc.h> + #include <linux/file.h> + #include <linux/firmware.h> ++#include <linux/version.h> + + #include <asm/io.h> + #include <asm/ar7/ar7.h> +@@ -492,7 +493,9 @@ static void avsar_release(struct device + } + + static struct device avsar = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + .bus_id = "vlynq", ++#endif + .release = avsar_release, + }; + +@@ -501,6 +504,9 @@ int shim_osLoadFWImage(unsigned char *pt + const struct firmware *fw_entry; + size_t size; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ dev_set_name(&avsar, "avsar"); ++#endif + printk("requesting firmware image \"ar0700xx.bin\"\n"); + if(device_register(&avsar) < 0) { + printk(KERN_ERR diff --git a/package/system/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch b/package/system/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch new file mode 100644 index 0000000000..feb6ea8605 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/180-git_headers_include.patch @@ -0,0 +1,54 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -76,10 +76,16 @@ + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++#include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + #include "dsl_hal_api.h" + #ifdef AR7_EFM +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -120,8 +120,13 @@ + #include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + /* Modules specific header files */ + #ifdef AR7_EFM +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -53,10 +53,16 @@ + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> ++#include <linux/version.h> + + #include <asm/io.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + #include <asm/ar7/ar7.h> + #include <asm/ar7/prom.h> ++#else ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++#endif + + #define _CPHAL_AAL5 + #define _CPHAL_SAR diff --git a/package/system/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch b/package/system/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch new file mode 100644 index 0000000000..52ebbc1529 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/190-2.6.32_proc_fixes.patch @@ -0,0 +1,79 @@ +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -215,7 +215,11 @@ led_reg_t ledreg[2]; + static struct led_funcs ledreg[2]; + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + #define DEV_DSLMOD CTL_UNNUMBERED ++#else ++#define DEV_DSLMOD 0 ++#endif + #define MAX_STR_SIZE 256 + #define DSL_MOD_SIZE 256 + +@@ -3615,9 +3619,16 @@ static int dslmod_sysctl(ctl_table *ctl, + */ + if(write) + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) + ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); +- ++#else ++ ret = proc_dostring(ctl, write, buffer, lenp, 0); ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + switch (ctl->ctl_name) ++#else ++ switch ((long)ctl->extra2) ++#endif + { + case DEV_DSLMOD: + ptr = strpbrk(info, " \t"); +@@ -3701,14 +3712,29 @@ static int dslmod_sysctl(ctl_table *ctl, + else + { + len += sprintf(info+len, mod_req); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) + ret = proc_dostring(ctl, write, filp, buffer, lenp, 0); ++#else ++ ret = proc_dostring(ctl, write, buffer, lenp, 0); ++#endif + } + return ret; + } + + + ctl_table dslmod_table[] = { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + {DEV_DSLMOD, "dslmod", info, DSL_MOD_SIZE, 0644, NULL, NULL, &dslmod_sysctl, &sysctl_string} ++#else ++ { ++ .procname = "dslmod", ++ .data = info, ++ .maxlen = DSL_MOD_SIZE, ++ .mode = 0644, ++ .proc_handler = &dslmod_sysctl, ++ .extra2 = (void *)DEV_DSLMOD, ++ } ++#endif + , + {0} + }; +@@ -3716,7 +3742,16 @@ ctl_table dslmod_table[] = { + /* Make sure that /proc/sys/dev is there */ + ctl_table dslmod_root_table[] = { + #ifdef CONFIG_PROC_FS ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + {CTL_DEV, "dev", NULL, 0, 0555, dslmod_table} ++ #else ++ { ++ .procname = "dev", ++ .maxlen = 0, ++ .mode = 0555, ++ .child = dslmod_table, ++ } ++ #endif + , + #endif /* CONFIG_PROC_FS */ + {0} diff --git a/package/system/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch b/package/system/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch new file mode 100644 index 0000000000..a3bff1b940 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/200-2.6.37_args.patch @@ -0,0 +1,36 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -2000,7 +2000,11 @@ static int __init tn7atm_register (Tn7At + + dgprintf (4, "device %s being registered\n", priv->name); + ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + mydev = atm_dev_register (priv->proc_name, &tn7atm_ops, -1, NULL); ++ #else ++ mydev = atm_dev_register (priv->proc_name, NULL, &tn7atm_ops, -1, NULL); ++ #endif + + if (mydev == NULL) + { +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -512,14 +512,17 @@ int shim_osLoadFWImage(unsigned char *pt + { + const struct firmware *fw_entry; + size_t size; ++ int ret; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + dev_set_name(&avsar, "avsar"); + #endif + printk("requesting firmware image \"ar0700xx.bin\"\n"); +- if(device_register(&avsar) < 0) { ++ dev_set_name(&avsar, "avsar"); ++ ret = device_register(&avsar); ++ if (ret < 0) { + printk(KERN_ERR +- "avsar: device_register fails\n"); ++ "avsar: device_register fails, error%i\n", ret); + return -1; + } + diff --git a/package/system/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch b/package/system/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch new file mode 100644 index 0000000000..975ebaf299 --- /dev/null +++ b/package/system/ar7-atm/patches-D7.05.01.00/210-3.3-remove-smp_lock.h.patch @@ -0,0 +1,33 @@ +--- a/tn7atm.c ++++ b/tn7atm.c +@@ -72,7 +72,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +--- a/tn7sar.c ++++ b/tn7sar.c +@@ -49,7 +49,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> +--- a/tn7dsl.c ++++ b/tn7dsl.c +@@ -108,7 +108,7 @@ + #include <linux/atmdev.h> + #include <linux/delay.h> + #include <linux/spinlock.h> +-#include <linux/smp_lock.h> ++#include <linux/interrupt.h> + #include <linux/proc_fs.h> + #include <linux/string.h> + #include <linux/ctype.h> diff --git a/package/system/avila-wdt/Makefile b/package/system/avila-wdt/Makefile new file mode 100644 index 0000000000..5bf6bf4ad0 --- /dev/null +++ b/package/system/avila-wdt/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=avila-wdt +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/avila-wdt + SUBMENU:=Other modules + TITLE:=GPIO hardware watchdog driver for modified Avila boards + DEPENDS:=@GPIO_SUPPORT @TARGET_ixp4xx + FILES:=$(PKG_BUILD_DIR)/avila-wdt.ko + AUTOLOAD:=$(call AutoLoad,10,avila-wdt) +endef + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,avila-wdt)) diff --git a/package/system/avila-wdt/src/Makefile b/package/system/avila-wdt/src/Makefile new file mode 100644 index 0000000000..90d90657ed --- /dev/null +++ b/package/system/avila-wdt/src/Makefile @@ -0,0 +1 @@ +obj-m := avila-wdt.o diff --git a/package/system/avila-wdt/src/avila-wdt.c b/package/system/avila-wdt/src/avila-wdt.c new file mode 100644 index 0000000000..981f3857ad --- /dev/null +++ b/package/system/avila-wdt/src/avila-wdt.c @@ -0,0 +1,231 @@ +/* + * avila-wdt.c + * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> + * + * based on: + * drivers/char/watchdog/ixp4xx_wdt.c + * + * Watchdog driver for Intel IXP4xx network processors + * + * Author: Deepak Saxena <dsaxena@plexity.net> + * + * Copyright 2004 (c) MontaVista, Software, Inc. + * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/jiffies.h> +#include <linux/timer.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/uaccess.h> +#include <mach/hardware.h> + +static int nowayout = WATCHDOG_NOWAYOUT; +static int heartbeat = 20; /* (secs) Default is 20 seconds */ +static unsigned long wdt_status; +static atomic_t wdt_counter; +struct timer_list wdt_timer; + +#define WDT_IN_USE 0 +#define WDT_OK_TO_CLOSE 1 +#define WDT_RUNNING 2 + +static void wdt_refresh(unsigned long data) +{ + if (test_bit(WDT_RUNNING, &wdt_status)) { + if (atomic_dec_and_test(&wdt_counter)) { + printk(KERN_WARNING "Avila watchdog expired, expect a reboot soon!\n"); + clear_bit(WDT_RUNNING, &wdt_status); + return; + } + } + + /* strobe to the watchdog */ + gpio_line_set(14, IXP4XX_GPIO_HIGH); + gpio_line_set(14, IXP4XX_GPIO_LOW); + + mod_timer(&wdt_timer, jiffies + msecs_to_jiffies(500)); +} + +static void wdt_enable(void) +{ + atomic_set(&wdt_counter, heartbeat * 2); + + /* Disable clock generator output on GPIO 14/15 */ + *IXP4XX_GPIO_GPCLKR &= ~(1 << 8); + + /* activate GPIO 14 out */ + gpio_line_config(14, IXP4XX_GPIO_OUT); + gpio_line_set(14, IXP4XX_GPIO_LOW); + + if (!test_bit(WDT_RUNNING, &wdt_status)) + wdt_refresh(0); + set_bit(WDT_RUNNING, &wdt_status); +} + +static void wdt_disable(void) +{ + /* Re-enable clock generator output on GPIO 14/15 */ + *IXP4XX_GPIO_GPCLKR |= (1 << 8); +} + +static int avila_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_IN_USE, &wdt_status)) + return -EBUSY; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + wdt_enable(); + return nonseekable_open(inode, file); +} + +static ssize_t +avila_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + set_bit(WDT_OK_TO_CLOSE, &wdt_status); + } + } + wdt_enable(); + } + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | + WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "Avila Watchdog", +}; + + +static long avila_wdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + int time; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + ret = put_user(0, (int *)arg); + break; + + case WDIOC_KEEPALIVE: + wdt_enable(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, (int *)arg); + if (ret) + break; + + if (time <= 0 || time > 60) { + ret = -EINVAL; + break; + } + + heartbeat = time; + wdt_enable(); + /* Fall through */ + + case WDIOC_GETTIMEOUT: + ret = put_user(heartbeat, (int *)arg); + break; + } + return ret; +} + +static int avila_wdt_release(struct inode *inode, struct file *file) +{ + if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) + wdt_disable(); + else + printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " + "timer will not stop\n"); + clear_bit(WDT_IN_USE, &wdt_status); + clear_bit(WDT_OK_TO_CLOSE, &wdt_status); + + return 0; +} + + +static const struct file_operations avila_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = avila_wdt_write, + .unlocked_ioctl = avila_wdt_ioctl, + .open = avila_wdt_open, + .release = avila_wdt_release, +}; + +static struct miscdevice avila_wdt_miscdev = { + .minor = WATCHDOG_MINOR + 1, + .name = "avila_watchdog", + .fops = &avila_wdt_fops, +}; + +static int __init avila_wdt_init(void) +{ + int ret; + + init_timer(&wdt_timer); + wdt_timer.expires = 0; + wdt_timer.data = 0; + wdt_timer.function = wdt_refresh; + ret = misc_register(&avila_wdt_miscdev); + if (ret == 0) + printk(KERN_INFO "Avila Watchdog Timer: heartbeat %d sec\n", + heartbeat); + return ret; +} + +static void __exit avila_wdt_exit(void) +{ + misc_deregister(&avila_wdt_miscdev); + del_timer(&wdt_timer); + wdt_disable(); +} + + +module_init(avila_wdt_init); +module_exit(avila_wdt_exit); + +MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); +MODULE_DESCRIPTION("Gateworks Avila Hardware Watchdog"); + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 20s)"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + diff --git a/package/system/brcm2708-gpu-fw/Makefile b/package/system/brcm2708-gpu-fw/Makefile new file mode 100644 index 0000000000..45c727caf5 --- /dev/null +++ b/package/system/brcm2708-gpu-fw/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=brcm2708-gpu-fw +PKG_REV:=29ce6bcf278e7e79cd8a2b84c6aa9db9864ca91d +PKG_VERSION:=20120529 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=git://github.com/raspberrypi/firmware.git +PKG_SOURCE_PROTO:=git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=$(PKG_REV) + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/brcm2708-gpu-fw + SECTION:=boot + CATEGORY:=Boot Loaders + DEPENDS:=@TARGET_brcm2708 + TITLE:=brcm2708-gpu-fw + DEFAULT:=y if (TARGET_brcm2708) +endef + +define Package/brcm2708-gpu-fw/description + GPU and kernel boot firmware for brcm2708. +endef + +define Build/Compile +endef + +define Build/InstallDev + $(INSTALL_DIR) $(BUILD_DIR)/brcm2708-gpu-fw-boot + $(CP) $(PKG_BUILD_DIR)/boot/* $(BUILD_DIR)/brcm2708-gpu-fw-boot +endef + +$(eval $(call BuildPackage,brcm2708-gpu-fw)) + diff --git a/package/system/button-hotplug/Makefile b/package/system/button-hotplug/Makefile new file mode 100644 index 0000000000..35ea6d411e --- /dev/null +++ b/package/system/button-hotplug/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2008-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=button-hotplug +PKG_RELEASE:=3 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/button-hotplug + SUBMENU:=Other modules + TITLE:=Button Hotplug driver + FILES:=$(PKG_BUILD_DIR)/button-hotplug.ko + AUTOLOAD:=$(call AutoLoad,30,button-hotplug) + KCONFIG:= +endef + +define KernelPackage/button-hotplug/description + Kernel module to generate button hotplug events +endef + +EXTRA_KCONFIG:= \ + CONFIG_BUTTON_HOTPLUG=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,button-hotplug)) diff --git a/package/system/button-hotplug/src/Kconfig b/package/system/button-hotplug/src/Kconfig new file mode 100644 index 0000000000..aa292e9c13 --- /dev/null +++ b/package/system/button-hotplug/src/Kconfig @@ -0,0 +1,2 @@ +config BUTTON_HOTPLUG + tristate "Button Hotplug driver" diff --git a/package/system/button-hotplug/src/Makefile b/package/system/button-hotplug/src/Makefile new file mode 100644 index 0000000000..230d604f8c --- /dev/null +++ b/package/system/button-hotplug/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_BUTTON_HOTPLUG} += button-hotplug.o
\ No newline at end of file diff --git a/package/system/button-hotplug/src/button-hotplug.c b/package/system/button-hotplug/src/button-hotplug.c new file mode 100644 index 0000000000..4a8c4a88ed --- /dev/null +++ b/package/system/button-hotplug/src/button-hotplug.c @@ -0,0 +1,349 @@ +/* + * Button Hotplug driver + * + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + * + * Based on the diag.c - GPIO interface driver for Broadcom boards + * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>, + * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2008 Andy Boyett <agb@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/version.h> +#include <linux/kmod.h> +#include <linux/input.h> + +#include <linux/workqueue.h> +#include <linux/skbuff.h> +#include <linux/netlink.h> +#include <linux/kobject.h> + +#define DRV_NAME "button-hotplug" +#define DRV_VERSION "0.4.1" +#define DRV_DESC "Button Hotplug driver" + +#define BH_SKB_SIZE 2048 + +#define PFX DRV_NAME ": " + +#undef BH_DEBUG + +#ifdef BH_DEBUG +#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args ) +#else +#define BH_DBG(fmt, args...) do {} while (0) +#endif + +#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args ) + +#ifndef BIT_MASK +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#endif + +struct bh_priv { + unsigned long *seen; + struct input_handle handle; +}; + +struct bh_event { + const char *name; + char *action; + unsigned long seen; + + struct sk_buff *skb; + struct work_struct work; +}; + +struct bh_map { + unsigned int code; + const char *name; +}; + +extern u64 uevent_next_seqnum(void); + +#define BH_MAP(_code, _name) \ + { \ + .code = (_code), \ + .name = (_name), \ + } + +static struct bh_map button_map[] = { + BH_MAP(BTN_0, "BTN_0"), + BH_MAP(BTN_1, "BTN_1"), + BH_MAP(BTN_2, "BTN_2"), + BH_MAP(BTN_3, "BTN_3"), + BH_MAP(BTN_4, "BTN_4"), + BH_MAP(BTN_5, "BTN_5"), + BH_MAP(BTN_6, "BTN_6"), + BH_MAP(BTN_7, "BTN_7"), + BH_MAP(BTN_8, "BTN_8"), + BH_MAP(BTN_9, "BTN_9"), + BH_MAP(KEY_RESTART, "reset"), +#ifdef KEY_WPS_BUTTON + BH_MAP(KEY_WPS_BUTTON, "wps"), +#endif /* KEY_WPS_BUTTON */ +}; + +/* -------------------------------------------------------------------------*/ + +static int bh_event_add_var(struct bh_event *event, int argv, + const char *format, ...) +{ + static char buf[128]; + char *s; + va_list args; + int len; + + if (argv) + return 0; + + va_start(args, format); + len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + if (len >= sizeof(buf)) { + BH_ERR("buffer size too small\n"); + WARN_ON(1); + return -ENOMEM; + } + + s = skb_put(event->skb, len + 1); + strcpy(s, buf); + + BH_DBG("added variable '%s'\n", s); + + return 0; +} + +static int button_hotplug_fill_event(struct bh_event *event) +{ + int ret; + + ret = bh_event_add_var(event, 0, "HOME=%s", "/"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "PATH=%s", + "/sbin:/bin:/usr/sbin:/usr/bin"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "ACTION=%s", event->action); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); + + return ret; +} + +static void button_hotplug_work(struct work_struct *work) +{ + struct bh_event *event = container_of(work, struct bh_event, work); + int ret = 0; + + event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); + if (!event->skb) + goto out_free_event; + + ret = bh_event_add_var(event, 0, "%s@", event->action); + if (ret) + goto out_free_skb; + + ret = button_hotplug_fill_event(event); + if (ret) + goto out_free_skb; + + NETLINK_CB(event->skb).dst_group = 1; + broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); + + out_free_skb: + if (ret) { + BH_ERR("work error %d\n", ret); + kfree_skb(event->skb); + } + out_free_event: + kfree(event); +} + +static int button_hotplug_create_event(const char *name, unsigned long seen, + int pressed) +{ + struct bh_event *event; + + BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n", + name, seen, pressed); + + event = kzalloc(sizeof(*event), GFP_KERNEL); + if (!event) + return -ENOMEM; + + event->name = name; + event->seen = seen; + event->action = pressed ? "pressed" : "released"; + + INIT_WORK(&event->work, (void *)(void *)button_hotplug_work); + schedule_work(&event->work); + + return 0; +} + +/* -------------------------------------------------------------------------*/ + +#ifdef CONFIG_HOTPLUG +static int button_get_index(unsigned int code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(button_map); i++) + if (button_map[i].code == code) + return i; + + return -1; +} +static void button_hotplug_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ + struct bh_priv *priv = handle->private; + unsigned long seen = jiffies; + int btn; + + BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value); + + if (type != EV_KEY) + return; + + btn = button_get_index(code); + if (btn < 0) + return; + + button_hotplug_create_event(button_map[btn].name, + (seen - priv->seen[btn]) / HZ, value); + priv->seen[btn] = seen; +} +#else +static void button_hotplug_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ +} +#endif /* CONFIG_HOTPLUG */ + +static int button_hotplug_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct bh_priv *priv; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(button_map); i++) + if (test_bit(button_map[i].code, dev->keybit)) + break; + + if (i == ARRAY_SIZE(button_map)) + return -ENODEV; + + priv = kzalloc(sizeof(*priv) + + (sizeof(unsigned long) * ARRAY_SIZE(button_map)), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->seen = (unsigned long *) &priv[1]; + priv->handle.private = priv; + priv->handle.dev = dev; + priv->handle.handler = handler; + priv->handle.name = DRV_NAME; + + ret = input_register_handle(&priv->handle); + if (ret) + goto err_free_priv; + + ret = input_open_device(&priv->handle); + if (ret) + goto err_unregister_handle; + + BH_DBG("connected to %s\n", dev->name); + + return 0; + + err_unregister_handle: + input_unregister_handle(&priv->handle); + + err_free_priv: + kfree(priv); + return ret; +} + +static void button_hotplug_disconnect(struct input_handle *handle) +{ + struct bh_priv *priv = handle->private; + + input_close_device(handle); + input_unregister_handle(handle); + + kfree(priv); +} + +static const struct input_device_id button_hotplug_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) }, + }, + { + /* Terminating entry */ + }, +}; + +MODULE_DEVICE_TABLE(input, button_hotplug_ids); + +static struct input_handler button_hotplug_handler = { + .event = button_hotplug_event, + .connect = button_hotplug_connect, + .disconnect = button_hotplug_disconnect, + .name = DRV_NAME, + .id_table = button_hotplug_ids, +}; + +/* -------------------------------------------------------------------------*/ + +static int __init button_hotplug_init(void) +{ + int ret; + + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); + ret = input_register_handler(&button_hotplug_handler); + if (ret) + BH_ERR("unable to register input handler\n"); + + return ret; +} +module_init(button_hotplug_init); + +static void __exit button_hotplug_exit(void) +{ + input_unregister_handler(&button_hotplug_handler); +} +module_exit(button_hotplug_exit); + +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); +MODULE_LICENSE("GPL v2"); + diff --git a/package/system/ep80579-drivers/Makefile b/package/system/ep80579-drivers/Makefile new file mode 100644 index 0000000000..61d3bc2a1f --- /dev/null +++ b/package/system/ep80579-drivers/Makefile @@ -0,0 +1,92 @@ +# +# Copyright (C) 2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ep80579-drivers +PKG_VERSION:=1.0.34 +PKG_RELEASE:=1 + +PKG_SOURCE:=Embedded.L.1.0.34.ADI.R100.tar.gz +PKG_SOURCE_URL:=ftp://ftp.adiengineering.com/Archive/OcracokeIsland/Drivers/Linux/1.0.34/ +PKG_MD5SUM:=61df9778f8c1f919257d2f48a0bcb000 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ep80579-drivers/Default + DEPENDS:=@TARGET_x86_ep80579 +endef + +define KernelPackage/ep80579-eth +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Network Devices + TITLE:=Intel EP80579 ethernet driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/src/GbE/gcu.ko \ + $(PKG_BUILD_DIR)/Embedded/src/GbE/iegbe.ko + AUTOLOAD:=$(call AutoLoad,40,gcu iegbe) +endef + +define KernelPackage/ep80579-misc +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Misc. Intel EP80579 drivers (DMA,, gpio) + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/src/EDMA/dma.ko \ + $(PKG_BUILD_DIR)/Embedded/src/GPIO/gpio.ko + AUTOLOAD:=$(call AutoLoad,40,gpio dma) +endef + +define KernelPackage/ep80579-can +$(call KernelPackage/ep80579-drivers/Default) + SUBMENU:=Other modules + TITLE:=Intel EP80579 CAN driver + FILES:= \ + $(PKG_BUILD_DIR)/Embedded/src/1588/timesync.ko \ + $(PKG_BUILD_DIR)/Embedded/src/CAN/can.ko + AUTOLOAD:=$(call AutoLoad,40,timesync can) +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + tar xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR)/ + $(Build/Patch) +endef + +define Build/Compile/Subdir + $(MAKE) -C "$(LINUX_DIR)" \ + KSRC="$(LINUX_DIR)" \ + KOBJ="$(LINUX_DIR)" \ + ENV_DIR=$(PKG_BUILD_DIR)/Embedded \ + SUBDIRS="$(PKG_BUILD_DIR)/Embedded/src/$(1)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCHIVER="$(TARGET_CROSS)ar" \ + COMPILER="$(TARGET_CC)" \ + LINKER="$(TARGET_CROSS)ld" \ + ARCH="$(LINUX_KARCH)" +endef + +define Build/Compile + $(call Build/Compile/Subdir,GbE) + $(call Build/Compile/Subdir,CAN) + $(call Build/Compile/Subdir,EDMA) + $(call Build/Compile/Subdir,GPIO) + $(call Build/Compile/Subdir,WDT) + $(call Build/Compile/Subdir,1588) +endef + +define KernelPackage/ep80579-eth/install +endef + +$(eval $(call KernelPackage,ep80579-can)) +$(eval $(call KernelPackage,ep80579-eth)) +$(eval $(call KernelPackage,ep80579-misc)) + diff --git a/package/system/ep80579-drivers/patches/001-igbe_update.patch b/package/system/ep80579-drivers/patches/001-igbe_update.patch new file mode 100644 index 0000000000..80ca0ef8b9 --- /dev/null +++ b/package/system/ep80579-drivers/patches/001-igbe_update.patch @@ -0,0 +1,11755 @@ +--- a/Embedded/src/GbE/gcu.h ++++ b/Embedded/src/GbE/gcu.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_if.c ++++ b/Embedded/src/GbE/gcu_if.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -330,10 +330,17 @@ gcu_write_verify(uint32_t phy_num, uint3 + */ + void gcu_iegbe_resume(struct pci_dev *pdev) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_restore_state(pdev); +- pci_enable_device(pdev); ++ if(!pci_enable_device(pdev)) ++ GCU_DBG("pci_enable_device failed!\n",); + + return; + } +@@ -348,6 +355,12 @@ EXPORT_SYMBOL(gcu_iegbe_resume); + */ + int gcu_iegbe_suspend(struct pci_dev *pdev, uint32_t state) + { ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif ++ + GCU_DBG("%s\n", __func__); + + pci_save_state(pdev); +--- a/Embedded/src/GbE/gcu_if.h ++++ b/Embedded/src/GbE/gcu_if.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/gcu_main.c ++++ b/Embedded/src/GbE/gcu_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -94,6 +94,7 @@ static struct pci_driver gcu_driver = { + + static struct gcu_adapter *global_adapter = 0; + static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED; ++static unsigned long g_intflags = 0; + + MODULE_AUTHOR("Intel(R) Corporation"); + MODULE_DESCRIPTION("Global Configuration Unit Driver"); +@@ -124,7 +125,7 @@ gcu_init_module(void) + + printk(KERN_INFO "%s\n", gcu_copyright); + +- ret = pci_module_init(&gcu_driver); ++ ret = pci_register_driver(&gcu_driver); + if(ret >= 0) { + register_reboot_notifier(&gcu_notifier_reboot); + } +@@ -199,8 +200,6 @@ gcu_probe(struct pci_dev *pdev, + return -ENOMEM; + } + +- SET_MODULE_OWNER(adapter); +- + pci_set_drvdata(pdev, adapter); + + adapter->pdev = pdev; +@@ -238,7 +237,6 @@ gcu_probe(struct pci_dev *pdev, + return 0; + } + +- + /** + * gcu_probe_err - gcu_probe error handler + * @err: gcu_err_type +@@ -295,7 +293,7 @@ gcu_notify_reboot(struct notifier_block + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &gcu_driver){ + gcu_suspend(pdev, 0x3); + } +@@ -318,6 +316,11 @@ static int + gcu_suspend(struct pci_dev *pdev, uint32_t state) + { + /*struct gcu_adapter *adapter = pci_get_drvdata(pdev); */ ++#if ( ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6) ) && \ ++ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ) ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct gcu_adapter *adapter = netdev_priv(netdev); ++#endif + + GCU_DBG("%s\n", __func__); + +@@ -338,7 +341,6 @@ gcu_suspend(struct pci_dev *pdev, uint32 + return state; + } + +- + /** + * alloc_gcu_adapter + * +@@ -412,7 +414,7 @@ gcu_get_adapter(void) + return NULL; + } + +- spin_lock(&global_adapter_spinlock); ++ spin_lock_irqsave(&global_adapter_spinlock, g_intflags); + + return global_adapter; + } +@@ -437,7 +439,7 @@ gcu_release_adapter(const struct gcu_ada + *adapter = 0; + } + +- spin_unlock(&global_adapter_spinlock); ++ spin_unlock_irqrestore(&global_adapter_spinlock, g_intflags); + + return; + } +--- a/Embedded/src/GbE/gcu_reg.h ++++ b/Embedded/src/GbE/gcu_reg.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe.7 ++++ b/Embedded/src/GbE/iegbe.7 +@@ -1,7 +1,7 @@ + + .\" GPL LICENSE SUMMARY + .\" +-.\" Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++.\" Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + .\" + .\" This program is free software; you can redistribute it and/or modify + .\" it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ + .\" Contact Information: + .\" Intel Corporation + .\" +-.\" version: Embedded.L.1.0.34 ++.\" version: Embedded.Release.Patch.L.1.0.7-5 + + .\" LICENSE + .\" +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -132,22 +132,6 @@ static const struct iegbe_stats iegbe_gs + { "cpp_master", E1000_STAT(icr_cpp_master) }, + { "stat", E1000_STAT(icr_stat) }, + #endif +-#ifdef IEGBE_GBE_WORKAROUND +- { "txqec", E1000_STAT(stats.txqec) }, +- { "tx_next_to_clean", E1000_STAT(stats.tx_next_to_clean) }, +- { "tx_next_to_use", E1000_STAT(stats.tx_next_to_use) }, +- { "num_tx_queues", E1000_STAT(stats.num_tx_queues) }, +- +- { "num_rx_buf_alloc", E1000_STAT(stats.num_rx_buf_alloc) }, +- { "rx_next_to_clean", E1000_STAT(stats.rx_next_to_clean) }, +- { "rx_next_to_use", E1000_STAT(stats.rx_next_to_use) }, +- { "cc_gt_num_rx", E1000_STAT(stats.cc_gt_num_rx) }, +- { "tx_hnet", E1000_STAT(stats.tx_hnet) }, +- { "tx_hnentu", E1000_STAT(stats.tx_hnentu) }, +- { "RUC", E1000_STAT(stats.ruc) }, +- { "RFC", E1000_STAT(stats.rfc) }, +- +-#endif + }; + #define E1000_STATS_LEN \ + sizeof(iegbe_gstrings_stats) / sizeof(struct iegbe_stats) +@@ -158,7 +142,7 @@ static const char iegbe_gstrings_test[][ + "Interrupt test (offline)", "Loopback test (offline)", + "Link test (on/offline)" + }; +-#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / (ETH_GSTRING_LEN)) ++#define E1000_TEST_LEN (sizeof(iegbe_gstrings_test) / ETH_GSTRING_LEN) + #endif /* ETHTOOL_TEST */ + + #define E1000_REGS_LEN 0x20 +@@ -176,9 +160,7 @@ iegbe_get_settings(struct net_device *ne + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + SUPPORTED_1000baseT_Full| +-#endif + SUPPORTED_Autoneg | + SUPPORTED_TP); + +@@ -259,21 +241,13 @@ iegbe_set_settings(struct net_device *ne + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | +-#ifndef IEGBE_10_100_ONLY + ADVERTISED_1000baseT_Full| +-#endif +- + ADVERTISED_Autoneg | + ADVERTISED_TP; + ecmd->advertising = hw->autoneg_advertised; + } +- } else { +- uint16_t duplex; +- +- // ethtool uses DUPLEX_FULL/DUPLEX_HALF +- // the driver needs FULL_DUPLEX/HALF_DUPLEX +- duplex = (ecmd->duplex == DUPLEX_FULL) ? FULL_DUPLEX : HALF_DUPLEX; +- if(iegbe_set_spd_dplx(adapter, ecmd->speed + duplex)) ++ } else ++ if(iegbe_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)){ + return -EINVAL; + } + /* reset the link */ +@@ -728,8 +702,8 @@ iegbe_set_ringparam(struct net_device *n + struct iegbe_rx_ring *rxdr, *rx_old, *rx_new; + int i, err, tx_ring_size, rx_ring_size; + +- tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; ++ tx_ring_size = sizeof(struct iegbe_tx_ring) * adapter->num_tx_queues; ++ rx_ring_size = sizeof(struct iegbe_rx_ring) * adapter->num_rx_queues; + + if (netif_running(adapter->netdev)){ + iegbe_down(adapter); +@@ -768,10 +742,10 @@ iegbe_set_ringparam(struct net_device *n + E1000_MAX_TXD : E1000_MAX_82544_TXD)); + E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); + +- for (i = 0; i < adapter->num_queues; i++) { +- txdr[i].count = txdr->count; +- rxdr[i].count = rxdr->count; +- } ++ for (i = 0; i < adapter->num_tx_queues; i++) ++ txdr[i].count = txdr->count; ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ rxdr[i].count = rxdr->count; + + if(netif_running(adapter->netdev)) { + /* Try to get new resources before deleting old */ +@@ -950,8 +924,7 @@ iegbe_eeprom_test(struct iegbe_adapter * + + static irqreturn_t + iegbe_test_intr(int irq, +- void *data, +- struct pt_regs *regs) ++ void *data) + { + struct net_device *netdev = (struct net_device *) data; + struct iegbe_adapter *adapter = netdev_priv(netdev); +@@ -973,7 +946,7 @@ iegbe_intr_test(struct iegbe_adapter *ad + /* Hook up test interrupt handler just for this test */ + if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { + shared_int = FALSE; +- } else if(request_irq(irq, &iegbe_test_intr, SA_SHIRQ, ++ } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ + *data = 1; + return -1; +@@ -1393,7 +1366,7 @@ iegbe_set_phy_loopback(struct iegbe_adap + * attempt this 10 times. + */ + while(iegbe_nonintegrated_phy_loopback(adapter) && +- count++ < 0xa) { }; ++ count++ < 0xa); + if(count < 0xb) { + return 0; + } +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -1,7 +1,7 @@ + /******************************************************************************* + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -21,7 +21,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -127,9 +127,12 @@ struct iegbe_adapter; + #define E1000_MIN_RXD 80 + #define E1000_MAX_82544_RXD 4096 + ++#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 + /* Supported Rx Buffer Sizes */ + #define E1000_RXBUFFER_128 128 /* Used for packet split */ + #define E1000_RXBUFFER_256 256 /* Used for packet split */ ++#define E1000_RXBUFFER_512 512 ++#define E1000_RXBUFFER_1024 1024 + #define E1000_RXBUFFER_2048 2048 + #define E1000_RXBUFFER_4096 4096 + #define E1000_RXBUFFER_8192 8192 +@@ -164,11 +167,9 @@ struct iegbe_adapter; + #define E1000_MASTER_SLAVE iegbe_ms_hw_default + #endif + +-#ifdef NETIF_F_HW_VLAN_TX +-#define E1000_MNG_VLAN_NONE -1 +-#endif ++#define E1000_MNG_VLAN_NONE (-1) + /* Number of packet split data buffers (not including the header buffer) */ +-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1 ++#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) + + /* only works for sizes that are powers of 2 */ + #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) +@@ -206,6 +207,7 @@ struct iegbe_tx_ring { + spinlock_t tx_lock; + uint16_t tdh; + uint16_t tdt; ++ boolean_t last_tx_tso; + uint64_t pkt; + }; + +@@ -228,6 +230,9 @@ struct iegbe_rx_ring { + struct iegbe_ps_page *ps_page; + struct iegbe_ps_page_dma *ps_page_dma; + ++ /* cpu for rx queue */ ++ int cpu; ++ + uint16_t rdh; + uint16_t rdt; + uint64_t pkt; +@@ -252,10 +257,8 @@ struct iegbe_adapter { + struct timer_list tx_fifo_stall_timer; + struct timer_list watchdog_timer; + struct timer_list phy_info_timer; +-#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; + uint16_t mng_vlan_id; +-#endif + uint32_t bd_number; + uint32_t rx_buffer_len; + uint32_t part_num; +@@ -265,8 +268,18 @@ struct iegbe_adapter { + uint16_t link_speed; + uint16_t link_duplex; + spinlock_t stats_lock; +- atomic_t irq_sem; +- struct work_struct tx_timeout_task; ++ spinlock_t tx_queue_lock; ++ unsigned int total_tx_bytes; ++ unsigned int total_tx_packets; ++ unsigned int total_rx_bytes; ++ unsigned int total_rx_packets; ++ /* Interrupt Throttle Rate */ ++ uint32_t itr; ++ uint32_t itr_setting; ++ uint16_t tx_itr; ++ uint16_t rx_itr; ++ ++ struct work_struct reset_task; + uint8_t fc_autoneg; + + #ifdef ETHTOOL_PHYS_ID +@@ -276,9 +289,8 @@ struct iegbe_adapter { + + /* TX */ + struct iegbe_tx_ring *tx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_MQ +- struct iegbe_tx_ring **cpu_tx_ring; /* per-cpu */ +-#endif ++ unsigned int restart_queue; ++ unsigned long tx_queue_len; + uint32_t txd_cmd; + uint32_t tx_int_delay; + uint32_t tx_abs_int_delay; +@@ -286,46 +298,33 @@ struct iegbe_adapter { + uint64_t gotcl_old; + uint64_t tpt_old; + uint64_t colc_old; ++ uint32_t tx_timeout_count; + uint32_t tx_fifo_head; + uint32_t tx_head_addr; + uint32_t tx_fifo_size; ++ uint8_t tx_timeout_factor; + atomic_t tx_fifo_stall; + boolean_t pcix_82544; + boolean_t detect_tx_hung; + + /* RX */ +-#ifdef CONFIG_E1000_NAPI +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, ++ bool (*clean_rx)(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +- boolean_t (*clean_rx) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND + void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring, +- int cleaned_count); +-#else +- void (*alloc_rx_buf) (struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif +- ++ struct iegbe_rx_ring *rx_ring, ++ int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ +-#ifdef CONFIG_E1000_NAPI ++ struct napi_struct napi; + struct net_device *polling_netdev; /* One per active queue */ +-#endif +-#ifdef CONFIG_E1000_MQ +- struct net_device **cpu_netdev; /* per-cpu */ +- struct call_async_data_struct rx_sched_call_data; +- int cpu_for_queue[4]; +-#endif +- int num_queues; ++ ++ int num_tx_queues; ++ int num_rx_queues; + + uint64_t hw_csum_err; + uint64_t hw_csum_good; + uint64_t rx_hdr_split; ++ uint32_t alloc_rx_buff_failed; + uint32_t rx_int_delay; + uint32_t rx_abs_int_delay; + boolean_t rx_csum; +@@ -334,8 +333,6 @@ struct iegbe_adapter { + uint64_t gorcl_old; + uint16_t rx_ps_bsize0; + +- /* Interrupt Throttle Rate */ +- uint32_t itr; + + /* OS defined structs */ + struct net_device *netdev; +@@ -378,7 +375,21 @@ struct iegbe_adapter { + #ifdef CONFIG_PCI_MSI + boolean_t have_msi; + #endif +-#define IEGBE_INTD_DISABLE 0x0400 ++ /* to not mess up cache alignment, always add to the bottom */ ++ boolean_t tso_force; ++ boolean_t smart_power_down; /* phy smart power down */ ++ boolean_t quad_port_a; ++ unsigned long flags; ++ uint32_t eeprom_wol; ++ int bars; ++ int need_ioport; + }; ++ ++enum iegbe_state_t { ++ __E1000_TESTING, ++ __E1000_RESETTING, ++ __E1000_DOWN ++}; ++#define IEGBE_INTD_DISABLE 0x0400 + #endif /* _IEGBE_H_ */ + +--- a/Embedded/src/GbE/iegbe_hw.c ++++ b/Embedded/src/GbE/iegbe_hw.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -2115,7 +2115,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + + ret_val = iegbe_oem_set_trans_gasket(hw); + if(ret_val){ +- return ret_val; ++ return ret_val; + } + ret_val = iegbe_oem_phy_is_full_duplex( + hw, (int *) &is_FullDuplex); +@@ -2164,7 +2164,7 @@ iegbe_config_mac_to_phy(struct iegbe_hw + } + /* Write the configured values back to the Device Control Reg. */ + E1000_WRITE_REG(hw, CTRL, ctrl); +- return E1000_SUCCESS; ++ return ret_val; + } + + /***************************************************************************** +@@ -2684,7 +2684,7 @@ iegbe_check_for_link(struct iegbe_hw *hw + + if(hw->autoneg_failed == 0) { + hw->autoneg_failed = 1; +- return 0; ++ return E1000_SUCCESS; + } + DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); + +@@ -5875,7 +5875,7 @@ iegbe_get_cable_length(struct iegbe_hw * + max_agc = cur_agc; + } + } +- ++ + /* This is to fix a Klockwork defect, that the array index might + * be out of bounds. 113 is table size */ + if (cur_agc < 0x71){ +--- a/Embedded/src/GbE/iegbe_hw.h ++++ b/Embedded/src/GbE/iegbe_hw.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -299,7 +299,7 @@ void iegbe_set_media_type(struct iegbe_h + /* Link Configuration */ + int32_t iegbe_setup_link(struct iegbe_hw *hw); + int32_t iegbe_phy_setup_autoneg(struct iegbe_hw *hw); +-void iegbe_config_collision_dist(struct iegbe_hw *hw); ++void iegbe_config_collision_dist(struct iegbe_hw *hw); + int32_t iegbe_config_fc_after_link_up(struct iegbe_hw *hw); + int32_t iegbe_check_for_link(struct iegbe_hw *hw); + int32_t iegbe_get_speed_and_duplex(struct iegbe_hw *hw, uint16_t * speed, uint16_t * duplex); +@@ -588,14 +588,6 @@ uint8_t iegbe_arc_subsystem_valid(struct + * o LSC = Link Status Change + */ + +-#ifdef IEGBE_GBE_WORKAROUND +-#define IMS_ENABLE_MASK ( \ +- E1000_IMS_RXT0 | \ +- E1000_IMS_TXQE | \ +- E1000_IMS_RXDMT0 | \ +- E1000_IMS_RXSEQ | \ +- E1000_IMS_LSC) +-#else + #define IMS_ENABLE_MASK ( \ + E1000_IMS_RXT0 | \ + E1000_IMS_TXDW | \ +@@ -606,8 +598,7 @@ uint8_t iegbe_arc_subsystem_valid(struct + E1000_ICR_PB | \ + E1000_ICR_CPP_TARGET | \ + E1000_ICR_CPP_MASTER | \ +- E1000_IMS_LSC) +-#endif ++ E1000_ICR_LSC) + + /* Number of high/low register pairs in the RAR. The RAR (Receive Address + * Registers) holds the directed and multicast addresses that we monitor. We +@@ -923,10 +914,15 @@ struct iegbe_ffvt_entry { + #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ + #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ + #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ +-// Register conflict, does not exist for ICP_xxxx hardware +-// #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_CTRL_AUX 0x000E0 /* Aux Control -RW */ ++#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ + #define E1000_RCTL 0x00100 /* RX Control - RW */ ++#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */ ++#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */ ++#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */ ++#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */ ++#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */ ++#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */ + #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ + #define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ + #define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ +@@ -1282,8 +1278,6 @@ struct iegbe_ffvt_entry { + #define E1000_82542_FFMT E1000_FFMT + #define E1000_82542_FFVT E1000_FFVT + #define E1000_82542_HOST_IF E1000_HOST_IF +-// Register conflict with ICP_xxxx hardware, no IAM +-// #define E1000_82542_IAM E1000_IAM + #define E1000_82542_EEMNGCTL E1000_EEMNGCTL + #define E1000_82542_PSRCTL E1000_PSRCTL + #define E1000_82542_RAID E1000_RAID +@@ -1329,6 +1323,7 @@ struct iegbe_hw_stats { + uint64_t algnerrc; + uint64_t symerrs; + uint64_t rxerrc; ++ uint64_t txerrc; + uint64_t mpc; + uint64_t scc; + uint64_t ecol; +@@ -1363,6 +1358,7 @@ struct iegbe_hw_stats { + uint64_t ruc; + uint64_t rfc; + uint64_t roc; ++ uint64_t rlerrc; + uint64_t rjc; + uint64_t mgprc; + uint64_t mgpdc; +@@ -1392,19 +1388,6 @@ struct iegbe_hw_stats { + uint64_t ictxqmtc; + uint64_t icrxdmtc; + uint64_t icrxoc; +-#ifdef IEGBE_GBE_WORKAROUND +- u64 txqec; +- u64 tx_next_to_clean; +- u64 tx_next_to_use; +- u64 cc_gt_num_rx; +- u64 tx_hnet; +- u64 tx_hnentu; +- u64 num_tx_queues; +- +- u64 num_rx_buf_alloc; +- u64 rx_next_to_clean; +- u64 rx_next_to_use; +-#endif + }; + + /* Structure containing variables used by the shared code (iegbe_hw.c) */ +@@ -1484,6 +1467,7 @@ struct iegbe_hw { + boolean_t ifs_params_forced; + boolean_t in_ifs_mode; + boolean_t mng_reg_access_disabled; ++ boolean_t rx_needs_kicking; + boolean_t icp_xxxx_is_link_up; + }; + +@@ -2358,17 +2342,23 @@ struct iegbe_host_command_info { + #define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF + #define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 + #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 ++#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 ++#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 + + /* PBA constants */ ++#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ + #define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ + #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ ++#define E1000_PBA_20K 0x0014 + #define E1000_PBA_22K 0x0016 + #define E1000_PBA_24K 0x0018 + #define E1000_PBA_30K 0x001E + #define E1000_PBA_32K 0x0020 ++#define E1000_PBA_34K 0x0022 + #define E1000_PBA_38K 0x0026 + #define E1000_PBA_40K 0x0028 + #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ ++#define E1000_PBS_16K E1000_PBA_16K + + /* Flow Control Constants */ + #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 +@@ -2899,7 +2889,7 @@ struct iegbe_host_command_info { + #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID + #define M88E1011_I_REV_4 0x04 + #define M88E1111_I_PHY_ID 0x01410CC2 +-#define M88E1141_E_PHY_ID 0x01410CD4 ++#define M88E1141_E_PHY_ID 0x01410CD0 + #define L1LXT971A_PHY_ID 0x001378E0 + + /* Miscellaneous PHY bit definitions. */ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -42,103 +42,15 @@ GPL LICENSE SUMMARY + + #include "iegbe.h" + #include "gcu_if.h" +- +-/* Change Log +- * 6.0.58 4/20/05 +- * o iegbe_set_spd_dplx tests for compatible speed/duplex specification +- * for fiber adapters +- * 6.0.57 4/19/05 +- * o Added code to fix register test failure for devices >= 82571 +- * +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * +- * 6.1.2 4/13/05 +- * o Fixed ethtool diagnostics +- * o Enabled flow control to take default eeprom settings +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while processing +- * MIIREG ioctl. +- * 6.0.55 3/23/05 +- * o Support for MODULE_VERSION +- * o Fix APM setting for 82544 based adapters +- * 6.0.54 3/26/05 +- * o Added a timer to expire packets that were deferred for cleanup +- * 6.0.52 3/15/05 +- * o Added stats_lock around iegbe_read_phy_reg commands to avoid concurrent +- * calls, one from mii_ioctl and other from within update_stats while +- * processing MIIREG ioctl. +- * 6.0.47 3/2/05 +- * o Added enhanced functionality to the loopback diags to wrap the +- * descriptor rings +- * o Added manageability vlan filtering workaround. +- * +- * 6.0.44+ 2/15/05 +- * o Added code to handle raw packet based DHCP packets +- * o Added code to fix the errata 10 buffer overflow issue +- * o Sync up with WR01-05 +- * o applied Anton's patch to resolve tx hang in hardware +- * o iegbe timeouts with early writeback patch +- * o Removed Queensport IDs +- * o fixed driver panic if MAC receives a bad large packets when packet +- * split is enabled +- * o Applied Andrew Mortons patch - iegbe stops working after resume +- * 5.2.29 12/24/03 +- * o Bug fix: Endianess issue causing ethtool diags to fail on ppc. +- * o Bug fix: Use pdev->irq instead of netdev->irq for MSI support. +- * o Report driver message on user override of InterruptThrottleRate module +- * parameter. +- * o Bug fix: Change I/O address storage from uint32_t to unsigned long. +- * o Feature: Added ethtool RINGPARAM support. +- * o Feature: Added netpoll support. +- * o Bug fix: Race between Tx queue and Tx clean fixed with a spin lock. +- * o Bug fix: Allow 1000/Full setting for autoneg param for fiber connections. +- * Jon D Mason [jonmason@us.ibm.com]. +- * +- * 5.2.22 10/15/03 +- * o Bug fix: SERDES devices might be connected to a back-plane switch that +- * doesn't support auto-neg, so add the capability to force 1000/Full. +- * Also, since forcing 1000/Full, sample RxSynchronize bit to detect link +- * state. +- * o Bug fix: Flow control settings for hi/lo watermark didn't consider +- * changes in the RX FIFO size, which could occur with Jumbo Frames or with +- * the reduced FIFO in 82547. +- * o Bug fix: Better propagation of error codes. +- * [Janice Girouard (janiceg -a-t- us.ibm.com)] +- * o Bug fix: hang under heavy Tx stress when running out of Tx descriptors; +- * wasn't clearing context descriptor when backing out of send because of +- * no-resource condition. +- * o Bug fix: check netif_running in dev->poll so we don't have to hang in +- * dev->close until all polls are finished. [Rober Olsson +- * (robert.olsson@data.slu.se)]. +- * o Revert TxDescriptor ring size back to 256 since change to 1024 wasn't +- * accepted into the kernel. +- * +- * 5.2.16 8/8/03 +- */ +- +-#ifdef IEGBE_GBE_WORKAROUND +-#define IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS 1 +-#endif ++#include <linux/ipv6.h> ++#include <net/ip6_checksum.h> + + char iegbe_driver_name[] = "iegbe"; + char iegbe_driver_string[] = "Gigabit Ethernet Controller Driver"; +-#ifndef CONFIG_E1000_NAPI +-#define DRIVERNAPI +-#else +-#define DRIVERNAPI "-NAPI" +-#endif +-#define DRV_VERSION "0.8.0"DRIVERNAPI ++#define DRV_VERSION "1.0.0-K28-NAPI" + char iegbe_driver_version[] = DRV_VERSION; +-char iegbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; ++char iegbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; + +-#define E1000_FIFO_HDR 0x10 +-#define E1000_82547_PAD_LEN 0x3E0 +-#define MINIMUM_DHCP_PACKET_SIZE 282 +-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) +-#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 + + /* iegbe_pci_tbl - PCI Device ID Table + * +@@ -148,95 +60,48 @@ char iegbe_copyright[] = "Copyright (c) + * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} + */ + static struct pci_device_id iegbe_pci_tbl[] = { +-/* INTEL_E1000_ETHERNET_DEVICE(0x1000), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1001), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1004), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1008), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1009), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x100F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1010), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1011), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1012), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1013), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1014), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1015), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1016), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1017), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1018), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1019), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x101E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1026), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1027), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1028), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x105F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1060), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1075), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1076), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1077), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1078), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x1079), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107D), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107E), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x107F), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108A), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108B), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x108C), */ +-/* INTEL_E1000_ETHERNET_DEVICE(0x109A), */ +- INTEL_E1000_ETHERNET_DEVICE(0x5040), +- INTEL_E1000_ETHERNET_DEVICE(0x5041), +- INTEL_E1000_ETHERNET_DEVICE(0x5042), +- INTEL_E1000_ETHERNET_DEVICE(0x5043), +- INTEL_E1000_ETHERNET_DEVICE(0x5044), +- INTEL_E1000_ETHERNET_DEVICE(0x5045), +- INTEL_E1000_ETHERNET_DEVICE(0x5046), +- INTEL_E1000_ETHERNET_DEVICE(0x5047), +- INTEL_E1000_ETHERNET_DEVICE(0x5048), +- INTEL_E1000_ETHERNET_DEVICE(0x5049), +- INTEL_E1000_ETHERNET_DEVICE(0x504A), +- INTEL_E1000_ETHERNET_DEVICE(0x504B), +- /* required last entry */ ++ INTEL_E1000_ETHERNET_DEVICE(0x5040), ++ INTEL_E1000_ETHERNET_DEVICE(0x5041), ++ INTEL_E1000_ETHERNET_DEVICE(0x5042), ++ INTEL_E1000_ETHERNET_DEVICE(0x5043), ++ INTEL_E1000_ETHERNET_DEVICE(0x5044), ++ INTEL_E1000_ETHERNET_DEVICE(0x5045), ++ INTEL_E1000_ETHERNET_DEVICE(0x5046), ++ INTEL_E1000_ETHERNET_DEVICE(0x5047), ++ INTEL_E1000_ETHERNET_DEVICE(0x5048), ++ INTEL_E1000_ETHERNET_DEVICE(0x5049), ++ INTEL_E1000_ETHERNET_DEVICE(0x504A), ++ INTEL_E1000_ETHERNET_DEVICE(0x504B), ++ /* required last entry */ + {0,} + }; + + MODULE_DEVICE_TABLE(pci, iegbe_pci_tbl); + +-DEFINE_SPINLOCK(print_lock); + + int iegbe_up(struct iegbe_adapter *adapter); + void iegbe_down(struct iegbe_adapter *adapter); ++void iegbe_reinit_locked(struct iegbe_adapter *adapter); + void iegbe_reset(struct iegbe_adapter *adapter); + int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx); + int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter); + int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_tx_resources(struct iegbe_adapter *adapter); + void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter); +-int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr); +-int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr); +-void iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-void iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); + void iegbe_update_stats(struct iegbe_adapter *adapter); +- + static int iegbe_init_module(void); + static void iegbe_exit_module(void); + static int iegbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + static void __devexit iegbe_remove(struct pci_dev *pdev); + static int iegbe_alloc_queues(struct iegbe_adapter *adapter); +-#ifdef CONFIG_E1000_MQ +-static void iegbe_setup_queue_mapping(struct iegbe_adapter *adapter); +-#endif + static int iegbe_sw_init(struct iegbe_adapter *adapter); + static int iegbe_open(struct net_device *netdev); + static int iegbe_close(struct net_device *netdev); +@@ -249,7 +114,8 @@ static void iegbe_clean_tx_ring(struct i + struct iegbe_tx_ring *tx_ring); + static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring); +-static void iegbe_set_multi(struct net_device *netdev); ++ ++static void iegbe_set_rx_mode(struct net_device *netdev); + static void iegbe_update_phy_info(unsigned long data); + static void iegbe_watchdog(unsigned long data); + static void iegbe_82547_tx_fifo_stall(unsigned long data); +@@ -257,66 +123,46 @@ static int iegbe_xmit_frame(struct sk_bu + static struct net_device_stats * iegbe_get_stats(struct net_device *netdev); + static int iegbe_change_mtu(struct net_device *netdev, int new_mtu); + static int iegbe_set_mac(struct net_device *netdev, void *p); +-static irqreturn_t iegbe_intr(int irq, void *data, struct pt_regs *regs); ++static irqreturn_t iegbe_intr(int irq, void *data); + +-void iegbe_tasklet(unsigned long); ++static irqreturn_t iegbe_intr_msi(int irq, void *data); + +-#ifndef IEGBE_GBE_WORKAROUND +-static boolean_t iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring); +-#endif +- +-#ifdef CONFIG_E1000_NAPI +-static int iegbe_clean(struct net_device *poll_dev, int *budget); +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static int iegbe_clean(struct napi_struct *napi, int budget); ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do); +-#else +-static boolean_t iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static boolean_t iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif + +-#ifdef IEGBE_GBE_WORKAROUND ++ + static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); + static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count); +-#else +-static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring); +-#endif ++ + + static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +-#ifdef SIOCGMIIPHY + static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, +- int cmd); +-#endif ++ int cmd); + void set_ethtool_ops(struct net_device *netdev); + extern int ethtool_ioctl(struct ifreq *ifr); + static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_leave_82542_rst(struct iegbe_adapter *adapter); + static void iegbe_tx_timeout(struct net_device *dev); +-static void iegbe_tx_timeout_task(struct net_device *dev); ++static void iegbe_reset_task(struct work_struct *work); + static void iegbe_smartspeed(struct iegbe_adapter *adapter); + static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, +- struct sk_buff *skb); ++ struct sk_buff *skb); + +-#ifdef NETIF_F_HW_VLAN_TX +-static void iegbe_vlan_rx_register(struct net_device *netdev, +- struct vlan_group *grp); ++static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); + static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_restore_vlan(struct iegbe_adapter *adapter); +-#endif + + static int iegbe_notify_reboot(struct notifier_block *, + unsigned long event, +@@ -331,15 +177,17 @@ static int iegbe_resume(struct pci_dev * + static void iegbe_netpoll (struct net_device *netdev); + #endif + +-#ifdef CONFIG_E1000_MQ +-/* for multiple Rx queues */ ++#define COPYBREAK_DEFAULT 256 ++static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; ++module_param(copybreak, uint, 0644); ++MODULE_PARM_DESC(copybreak, ++ "Maximum size of packet that is copied to a new buffer on receive"); + void iegbe_rx_schedule(void *data); +-#endif + + struct notifier_block iegbe_notifier_reboot = { +- .notifier_call = iegbe_notify_reboot, +- .next = NULL, +- .priority = 0 ++ .notifier_call = iegbe_notify_reboot, ++ .next = NULL, ++ .priority = 0 + }; + + /* Exported from other modules */ +@@ -347,14 +195,14 @@ struct notifier_block iegbe_notifier_reb + extern void iegbe_check_options(struct iegbe_adapter *adapter); + + static struct pci_driver iegbe_driver = { +- .name = iegbe_driver_name, +- .id_table = iegbe_pci_tbl, +- .probe = iegbe_probe, +- .remove = __devexit_p(iegbe_remove), +- /* Power Managment Hooks */ ++ .name = iegbe_driver_name, ++ .id_table = iegbe_pci_tbl, ++ .probe = iegbe_probe, ++ .remove = __devexit_p(iegbe_remove), ++ /* Power Managment Hooks */ + #ifdef CONFIG_PM +- .suspend = iegbe_suspend, +- .resume = iegbe_resume ++ .suspend = iegbe_suspend, ++ .resume = iegbe_resume + #endif + }; + +@@ -364,46 +212,17 @@ MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + + static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; +-module_param(debug, int, 0); ++module_param(debug, int, 0x0); + MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +-static uint8_t gcu_suspend = 0; +-static uint8_t gcu_resume = 0; ++static uint8_t gcu_suspend = 0x0; ++static uint8_t gcu_resume = 0x0; + struct pci_dev *gcu = NULL; + +-unsigned long tasklet_data; +-DECLARE_TASKLET(iegbe_reset_tasklet, iegbe_tasklet, (unsigned long) &tasklet_data); + + /** + * iegbe_iegbe_tasklet -* + **/ +-void iegbe_tasklet(unsigned long data) +-{ +- char* err_msg = "TEST"; +- uint32_t *icr = (uint32_t*) data; +- uint32_t gbe = *icr & 0x000000FF; +- if( *icr & E1000_ICR_RX_DESC_FIFO_PAR) { /* 21 */ +- err_msg = "DMA Transmit Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_TX_DESC_FIFO_PAR) { /* 20 */ +- err_msg = "DMA Receive Descriptor 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_PB) { /* 23 */ +- err_msg = "DMA Packet Buffer 2-bit ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_TARGET) { /* 27 */ +- err_msg = "Statistic Register ECC Error!"; +- } +- if( *icr & E1000_ICR_CPP_MASTER) { +- err_msg = "CPP Error!"; +- } +- spin_lock(&print_lock); +- printk("IEGBE%d: System Reset due to: %s\n", gbe, err_msg); +- dump_stack(); +- spin_unlock(&print_lock); +- panic(err_msg); +- return; +-} + /** + * iegbe_init_module - Driver Registration Routine + * +@@ -411,21 +230,24 @@ void iegbe_tasklet(unsigned long data) + * loaded. All it does is register with the PCI subsystem. + **/ + +-static int __init +-iegbe_init_module(void) ++static int __init iegbe_init_module(void) + { +- int ret; ++ int ret; + + printk(KERN_INFO "%s - version %s\n", +- iegbe_driver_string, iegbe_driver_version); ++ iegbe_driver_string, iegbe_driver_version); + +- printk(KERN_INFO "%s\n", iegbe_copyright); ++ printk(KERN_INFO "%s\n", iegbe_copyright); + +- ret = pci_module_init(&iegbe_driver); +- if(ret >= 0) { +- register_reboot_notifier(&iegbe_notifier_reboot); +- } +- return ret; ++ ret = pci_register_driver(&iegbe_driver); ++ if (copybreak != COPYBREAK_DEFAULT) { ++ if (copybreak == 0) ++ printk(KERN_INFO "iegbe: copybreak disabled\n"); ++ else ++ printk(KERN_INFO "iegbe: copybreak enabled for " ++ "packets <= %u bytes\n", copybreak); ++ } ++ return ret; + } + + module_init(iegbe_init_module); +@@ -437,29 +259,51 @@ module_init(iegbe_init_module); + * from memory. + **/ + +-static void __exit +-iegbe_exit_module(void) ++static void __exit iegbe_exit_module(void) + { +- +- unregister_reboot_notifier(&iegbe_notifier_reboot); +- pci_unregister_driver(&iegbe_driver); ++ pci_unregister_driver(&iegbe_driver); + } + + module_exit(iegbe_exit_module); + ++static int iegbe_request_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ irq_handler_t handler = iegbe_intr; ++ int irq_flags = IRQF_SHARED; ++ int err; ++ adapter->have_msi = !pci_enable_msi(adapter->pdev); ++ if (adapter->have_msi) { ++ handler = iegbe_intr_msi; ++ irq_flags = 0; ++ } ++ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, ++ netdev); ++ if (err) { ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate interrupt Error: %d\n", err); ++ } ++ return err; ++} ++static void iegbe_free_irq(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ free_irq(adapter->pdev->irq, netdev); ++ if (adapter->have_msi) ++ pci_disable_msi(adapter->pdev); ++} + /** + * iegbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +-static inline void +-iegbe_irq_disable(struct iegbe_adapter *adapter) ++static void iegbe_irq_disable(struct iegbe_adapter *adapter) + { +- +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(&adapter->hw, IMC, ~0); +- E1000_WRITE_FLUSH(&adapter->hw); +- synchronize_irq(adapter->pdev->irq); ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ synchronize_irq(adapter->pdev->irq); + } + + /** +@@ -470,244 +314,414 @@ iegbe_irq_disable(struct iegbe_adapter * + static inline void + iegbe_irq_enable(struct iegbe_adapter *adapter) + { +- +- if(likely(atomic_dec_and_test(&adapter->irq_sem))) { +- E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); +- E1000_WRITE_FLUSH(&adapter->hw); +- } ++ E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#ifdef NETIF_F_HW_VLAN_TX +-void +-iegbe_update_mng_vlan(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- uint16_t vid = adapter->hw.mng_cookie.vlan_id; +- uint16_t old_vid = adapter->mng_vlan_id; + +- if(adapter->vlgrp) { +- if(!adapter->vlgrp->vlan_devices[vid]) { +- if(adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { +- iegbe_vlan_rx_add_vid(netdev, vid); +- adapter->mng_vlan_id = vid; +- } else { +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) && +- (vid != old_vid) && +- !adapter->vlgrp->vlan_devices[old_vid]) { +- iegbe_vlan_rx_kill_vid(netdev, old_vid); +- } +- } +-} ++static void iegbe_update_mng_vlan(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ u16 vid = hw->mng_cookie.vlan_id; ++ u16 old_vid = adapter->mng_vlan_id; ++ if (adapter->vlgrp) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) { ++ if (hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { ++ iegbe_vlan_rx_add_vid(netdev, vid); ++ adapter->mng_vlan_id = vid; ++ } else ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ ++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && ++ (vid != old_vid) && ++ !vlan_group_get_device(adapter->vlgrp, old_vid)) ++ iegbe_vlan_rx_kill_vid(netdev, old_vid); ++ } else ++ adapter->mng_vlan_id = vid; ++ } + } +-#endif + +-int +-iegbe_up(struct iegbe_adapter *adapter) ++/** ++ * iegbe_configure - configure the hardware for RX and TX ++ * @adapter = private board structure ++ **/ ++static void iegbe_configure(struct iegbe_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; +- int i, err; +- uint16_t pci_cmd; +- +- /* hardware has been reset, we need to reload some things */ +- +- /* Reset the PHY if it was previously powered down */ +- if(adapter->hw.media_type == iegbe_media_type_copper +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw))) { +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); +- if(mii_reg & MII_CR_POWER_DOWN){ +- iegbe_phy_reset(&adapter->hw); +- } +- } ++ int i; + +- iegbe_set_multi(netdev); ++ iegbe_set_rx_mode(netdev); + +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_restore_vlan(adapter); +-#endif + + iegbe_configure_tx(adapter); + iegbe_setup_rctl(adapter); + iegbe_configure_rx(adapter); ++ /* call E1000_DESC_UNUSED which always leaves ++ * at least 1 descriptor unused to make sure ++ * next_to_use != next_to_clean */ ++ for (i = 0; i < adapter->num_rx_queues; i++) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[i]; ++ adapter->alloc_rx_buf(adapter, ring, ++ E1000_DESC_UNUSED(ring)); ++ } + +-#ifdef IEGBE_GBE_WORKAROUND +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- for (i = 0; i < adapter->num_queues; i++) +- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]); +-#endif ++ adapter->tx_queue_len = netdev->tx_queue_len; ++} + +-#ifdef CONFIG_PCI_MSI +- if(adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) { +- adapter->have_msi = TRUE; +- if((err = pci_enable_msi(adapter->pdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate MSI interrupt Error: %d\n", err); +- adapter->have_msi = FALSE; +- } +- } +- pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); +- pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd | IEGBE_INTD_DISABLE); ++int iegbe_up(struct iegbe_adapter *adapter) ++{ ++ /* hardware has been reset, we need to reload some things */ ++ iegbe_configure(adapter); + +-#endif +- if((err = request_irq(adapter->pdev->irq, &iegbe_intr, +- SA_SHIRQ | SA_SAMPLE_RANDOM, +- netdev->name, netdev))) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate interrupt Error: %d\n", err); +- return err; +- } ++ clear_bit(__E1000_DOWN, &adapter->flags); + +- mod_timer(&adapter->watchdog_timer, jiffies); ++ napi_enable(&adapter->napi); + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_enable(netdev); +-#endif + iegbe_irq_enable(adapter); + ++ adapter->hw.get_link_status = 0x1; + return 0; + } + +-void +-iegbe_down(struct iegbe_adapter *adapter) +-{ +- struct net_device *netdev = adapter->netdev; +- +- iegbe_irq_disable(adapter); +-#ifdef CONFIG_E1000_MQ +- while (atomic_read(&adapter->rx_sched_call_data.count) != 0) { }; +-#endif +- free_irq(adapter->pdev->irq, netdev); +-#ifdef CONFIG_PCI_MSI +- if((adapter->hw.mac_type > iegbe_82547_rev_2 +- || adapter->hw.mac_type == iegbe_icp_xxxx) +- && adapter->have_msi == TRUE) { +- pci_disable_msi(adapter->pdev); +- } +-#endif +- del_timer_sync(&adapter->tx_fifo_stall_timer); +- del_timer_sync(&adapter->watchdog_timer); +- del_timer_sync(&adapter->phy_info_timer); ++/** ++ * iegbe_power_up_phy - restore link in case the phy was powered down ++ * @adapter: address of board private structure ++ * ++ * The phy may be powered down to save power and turn off link when the ++ * driver is unloaded and wake on lan is not enabled (among others) ++ * *** this routine MUST be followed by a call to iegbe_reset *** ++ * ++ **/ + +-#ifdef CONFIG_E1000_NAPI +- netif_poll_disable(netdev); +-#endif +- adapter->link_speed = 0; +- adapter->link_duplex = 0; +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++void iegbe_power_up_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 mii_reg = 0; + +- iegbe_reset(adapter); +- iegbe_clean_all_tx_rings(adapter); +- iegbe_clean_all_rx_rings(adapter); ++ /* Just clear the power down bit to wake the phy back up */ ++ if (hw->media_type == iegbe_media_type_copper) { ++ /* according to the manual, the phy will retain its ++ * settings across a power-down/up cycle */ ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); ++ mii_reg &= ~MII_CR_POWER_DOWN; ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); ++ } ++} + +- /* If WoL is not enabled and management mode is not IAMT +- * or if WoL is not enabled and OEM PHY is copper based, +- * power down the PHY so no link is implied when interface is down */ +- if(!adapter->wol +- && ((adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.media_type == iegbe_media_type_copper +- && !iegbe_check_mng_mode(&adapter->hw) +- && !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) +- || (adapter->hw.media_type == iegbe_media_type_oem +- && iegbe_oem_phy_is_copper(&adapter->hw)))){ ++static void iegbe_power_down_phy(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; + +- uint16_t mii_reg; +- iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg); ++ /* Power down the PHY so no link is implied when interface is down * ++ * The PHY cannot be powered down if any of the following is true * ++ * (a) WoL is enabled ++ * (b) AMT is active ++ * (c) SoL/IDER session is active */ ++ if (!adapter->wol && hw->mac_type >= iegbe_82540 && ++ hw->media_type == iegbe_media_type_copper) { ++ u16 mii_reg = 0; ++ ++ switch (hw->mac_type) { ++ case iegbe_82540: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_82547: ++ case iegbe_82547_rev_2: ++ if (E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) ++ goto out; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ if (iegbe_check_mng_mode(hw) || ++ iegbe_check_phy_reset_block(hw)) ++ goto out; ++ break; ++ default: ++ goto out; ++ } ++ iegbe_read_phy_reg(hw, PHY_CTRL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg); ++ iegbe_write_phy_reg(hw, PHY_CTRL, mii_reg); + mdelay(1); + } ++out: ++ return; + } + +-void +-iegbe_reset(struct iegbe_adapter *adapter) ++void iegbe_down(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t pba, manc; +- uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF; +- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF; ++ struct net_device *netdev = adapter->netdev; + ++ /* signal that we're down so the interrupt handler does not ++ * reschedule our watchdog timer */ ++ set_bit(__E1000_DOWN, &adapter->flags); + +- /* Repartition Pba for greater than 9k mtu +- * To take effect CTRL.RST is required. +- */ ++ napi_disable(&adapter->napi); + +- switch (adapter->hw.mac_type) { +- case iegbe_82547: +- case iegbe_82547_rev_2: +- pba = E1000_PBA_30K; +- break; +- case iegbe_82571: +- case iegbe_82572: +- pba = E1000_PBA_38K; +- break; +- case iegbe_82573: +- pba = E1000_PBA_12K; ++ iegbe_irq_disable(adapter); ++ ++ del_timer_sync(&adapter->tx_fifo_stall_timer); ++ del_timer_sync(&adapter->watchdog_timer); ++ del_timer_sync(&adapter->phy_info_timer); ++ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->link_speed = 0; ++ adapter->link_duplex = 0; ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ ++ iegbe_reset(adapter); ++ iegbe_clean_all_tx_rings(adapter); ++ iegbe_clean_all_rx_rings(adapter); ++} ++void iegbe_reinit_locked(struct iegbe_adapter *adapter) ++{ ++ WARN_ON(in_interrupt()); ++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) ++ msleep(1); ++ iegbe_down(adapter); ++ iegbe_up(adapter); ++ clear_bit(__E1000_RESETTING, &adapter->flags); ++} ++ ++void iegbe_reset(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 pba = 0, tx_space, min_tx_space, min_rx_space; ++ u16 fc_high_water_mark = E1000_FC_HIGH_DIFF; ++ bool legacy_pba_adjust = false; ++ ++ /* Repartition Pba for greater than 9k mtu ++ * To take effect CTRL.RST is required. ++ */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ case iegbe_82544: ++ case iegbe_82540: ++ case iegbe_82541: ++ case iegbe_82541_rev_2: ++ case iegbe_icp_xxxx: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_48K; + break; +- default: ++ case iegbe_82545: ++ case iegbe_82545_rev_3: ++ case iegbe_82546: ++ case iegbe_82546_rev_3: + pba = E1000_PBA_48K; + break; +- } ++ case iegbe_82547: ++ case iegbe_82573: ++ case iegbe_82547_rev_2: ++ legacy_pba_adjust = true; ++ pba = E1000_PBA_30K; ++ break; ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_undefined: ++ case iegbe_num_macs: ++ break; ++ } ++ ++ if (legacy_pba_adjust) { ++ if (adapter->netdev->mtu > E1000_RXBUFFER_8192) ++ pba -= 8; /* allocate more FIFO for Tx */ ++ /* send an XOFF when there is enough space in the ++ * Rx FIFO to hold one extra full size Rx packet ++ */ + +- if((adapter->hw.mac_type != iegbe_82573) && +- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) { +- pba -= 0x8; /* allocate more FIFO for Tx */ +- /* send an XOFF when there is enough space in the +- * Rx FIFO to hold one extra full size Rx packet +- */ +- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE + +- ETHERNET_FCS_SIZE + 0x1; +- fc_low_water_mark = fc_high_water_mark + 0x8; +- } + ++ if (hw->mac_type == iegbe_82547) { ++ adapter->tx_fifo_head = 0; ++ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; ++ adapter->tx_fifo_size = ++ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; ++ atomic_set(&adapter->tx_fifo_stall, 0); ++ } ++ } else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ E1000_WRITE_REG(&adapter->hw, PBA, pba); ++ ++ /* To maintain wire speed transmits, the Tx FIFO should be ++ * large enough to accomodate two full transmit packets, ++ * rounded up to the next 1KB and expressed in KB. Likewise, ++ * the Rx FIFO should be large enough to accomodate at least ++ * one full receive packet and is similarly rounded up and ++ * expressed in KB. */ ++ pba = E1000_READ_REG(&adapter->hw, PBA); ++ /* upper 16 bits has Tx packet buffer allocation size in KB */ ++ tx_space = pba >> 16; ++ /* lower 16 bits has Rx packet buffer allocation size in KB */ ++ pba &= 0xffff; ++ /* don't include ethernet FCS because hardware appends/strips */ ++ min_rx_space = adapter->netdev->mtu + ENET_HEADER_SIZE + ++ VLAN_TAG_SIZE; ++ min_tx_space = min_rx_space; ++ min_tx_space *= 2; ++ min_tx_space = ALIGN(min_tx_space, 1024); ++ min_tx_space >>= 10; ++ min_rx_space = ALIGN(min_rx_space, 1024); ++ min_rx_space >>= 10; ++ ++ /* If current Tx allocation is less than the min Tx FIFO size, ++ * and the min Tx FIFO size is less than the current Rx FIFO ++ * allocation, take space away from current Rx allocation */ ++ if (tx_space < min_tx_space && ++ ((min_tx_space - tx_space) < pba)) { ++ pba = pba - (min_tx_space - tx_space); ++ ++ /* PCI/PCIx hardware has PBA alignment constraints */ ++ switch (hw->mac_type) { ++ case iegbe_82545 ... iegbe_82546_rev_3: ++ pba &= ~(E1000_PBA_8K - 1); ++ break; ++ default: ++ break; ++ } + +- if(adapter->hw.mac_type == iegbe_82547) { +- adapter->tx_fifo_head = 0; +- adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; +- adapter->tx_fifo_size = +- (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; +- atomic_set(&adapter->tx_fifo_stall, 0); ++ /* if short on rx space, rx wins and must trump tx ++ * adjustment or use Early Receive if available */ ++ if (pba < min_rx_space) { ++ switch (hw->mac_type) { ++ case iegbe_82573: ++ /* ERT enabled in iegbe_configure_rx */ ++ break; ++ default: ++ pba = min_rx_space; ++ break; ++ } ++ } ++ } + } + + E1000_WRITE_REG(&adapter->hw, PBA, pba); + + /* flow control settings */ +- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_high_water_mark; +- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) - +- fc_low_water_mark; +- adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; +- adapter->hw.fc_send_xon = 1; +- adapter->hw.fc = adapter->hw.original_fc; ++ /* Set the FC high water mark to 90% of the FIFO size. ++ * Required to clear last 3 LSB */ ++ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8; ++ /* We can't use 90% on small FIFOs because the remainder ++ * would be less than 1 full frame. In this case, we size ++ * it to allow at least a full frame above the high water ++ * mark. */ ++ if (pba < E1000_PBA_16K) ++ fc_high_water_mark = (pba * 1024) - 1600; ++ ++ hw->fc_high_water = fc_high_water_mark; ++ hw->fc_low_water = fc_high_water_mark - 8; ++ hw->fc_pause_time = E1000_FC_PAUSE_TIME; ++ hw->fc_send_xon = 1; ++ hw->fc = hw->original_fc; + + /* Allow time for pending master requests to run */ +- iegbe_reset_hw(&adapter->hw); +- if(adapter->hw.mac_type >= iegbe_82544){ ++ iegbe_reset_hw(hw); ++ if (hw->mac_type >= iegbe_82544) + E1000_WRITE_REG(&adapter->hw, WUC, 0); +- } +- if(iegbe_init_hw(&adapter->hw)) { ++ ++ if (iegbe_init_hw(hw)) + DPRINTK(PROBE, ERR, "Hardware Error\n"); +- } +-#ifdef NETIF_F_HW_VLAN_TX + iegbe_update_mng_vlan(adapter); +-#endif ++ ++ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ ++ if (hw->mac_type >= iegbe_82544 && ++ hw->mac_type <= iegbe_82547_rev_2 && ++ hw->autoneg == 1 && ++ hw->autoneg_advertised == ADVERTISE_1000_FULL) { ++ u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* clear phy power management bit if we are in gig only mode, ++ * which if enabled will attempt negotiation to 100Mb, which ++ * can cause a loss of link at power off or driver unload */ ++ ctrl &= ~E1000_CTRL_SWDPIN3; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } ++ + /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ + E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE); + +- iegbe_reset_adaptive(&adapter->hw); +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); +- if(adapter->en_mng_pt) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ iegbe_reset_adaptive(hw); ++ iegbe_phy_get_info(hw, &adapter->phy_info); ++ ++ if (!adapter->smart_power_down && ++ (hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572)) { ++ u16 phy_data = 0; ++ /* speed up time to link by disabling smart power down, ignore ++ * the return value of this function because there is nothing ++ * different we would do if it failed */ ++ iegbe_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ &phy_data); ++ phy_data &= ~IGP02E1000_PM_SPD; ++ iegbe_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, ++ phy_data); ++ } ++ ++} ++ ++/** ++ * Dump the eeprom for users having checksum issues ++ **/ ++static void iegbe_dump_eeprom(struct iegbe_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ struct ethtool_eeprom eeprom; ++ const struct ethtool_ops *ops = netdev->ethtool_ops; ++ u8 *data; ++ int i; ++ u16 csum_old, csum_new = 0; ++ ++ eeprom.len = ops->get_eeprom_len(netdev); ++ eeprom.offset = 0; ++ ++ data = kmalloc(eeprom.len, GFP_KERNEL); ++ if (!data) { ++ printk(KERN_ERR "Unable to allocate memory to dump EEPROM" ++ " data\n"); ++ return; + } ++ ++ ops->get_eeprom(netdev, &eeprom, data); ++ ++ csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + ++ (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); ++ for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) ++ csum_new += data[i] + (data[i + 1] << 8); ++ csum_new = EEPROM_SUM - csum_new; ++ ++ printk(KERN_ERR "/*********************/\n"); ++ printk(KERN_ERR "Current EEPROM Checksum : 0x%04x\n", csum_old); ++ printk(KERN_ERR "Calculated : 0x%04x\n", csum_new); ++ ++ printk(KERN_ERR "Offset Values\n"); ++ printk(KERN_ERR "======== ======\n"); ++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); ++ ++ printk(KERN_ERR "Include this output when contacting your support " ++ "provider.\n"); ++ printk(KERN_ERR "This is not a software error! Something bad " ++ "happened to your hardware or\n"); ++ printk(KERN_ERR "EEPROM image. Ignoring this " ++ "problem could result in further problems,\n"); ++ printk(KERN_ERR "possibly loss of data, corruption or system hangs!\n"); ++ printk(KERN_ERR "The MAC Address will be reset to 00:00:00:00:00:00, " ++ "which is invalid\n"); ++ printk(KERN_ERR "and requires you to set the proper MAC " ++ "address manually before continuing\n"); ++ printk(KERN_ERR "to enable this network device.\n"); ++ printk(KERN_ERR "Please inspect the EEPROM dump and report the issue " ++ "to your hardware vendor\n"); ++ printk(KERN_ERR "or Intel Customer Support.\n"); ++ printk(KERN_ERR "/*********************/\n"); ++ ++ kfree(data); + } + + /** +@@ -721,184 +735,166 @@ iegbe_reset(struct iegbe_adapter *adapte + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +- +-static int __devinit +-iegbe_probe(struct pci_dev *pdev, ++static int __devinit iegbe_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { +- struct net_device *netdev; +- struct iegbe_adapter *adapter; +- unsigned long mmio_start, mmio_len; +- uint32_t ctrl_ext; +- uint32_t swsm; ++ struct net_device *netdev; ++ struct iegbe_adapter *adapter; ++ struct iegbe_hw *hw; + + static int cards_found = 0; ++ int i, err, pci_using_dac; ++ u16 eeprom_data = 0; ++ u16 eeprom_apme_mask = E1000_EEPROM_APME; ++ int bars; ++ DECLARE_MAC_BUF(mac); + +- int i, err, pci_using_dac; +- uint16_t eeprom_data = 0; +- uint16_t eeprom_apme_mask = E1000_EEPROM_APME; ++ bars = pci_select_bars(pdev, IORESOURCE_MEM); ++ err = pci_enable_device(pdev); + ++ if (err) ++ return err; + +- if((err = pci_enable_device(pdev))) { +- return err; +- } +- if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT))) { ++ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && ++ !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { + pci_using_dac = 1; +- } else { +- if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT))) { +- E1000_ERR("No usable DMA configuration, aborting\n"); +- return err; +- } ++ } else { ++ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ if (err) { ++ E1000_ERR("No usable DMA configuration, " ++ "aborting\n"); ++ goto err_dma; ++ } ++ } + pci_using_dac = 0; +- } +- +- if((err = pci_request_regions(pdev, iegbe_driver_name))) { +- return err; + } +- pci_set_master(pdev); + +- netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); +- if(!netdev) { +- err = -ENOMEM; +- goto err_alloc_etherdev; +- } ++ err = pci_request_selected_regions(pdev, bars, iegbe_driver_name); ++ if (err) ++ goto err_pci_reg; ++ ++ pci_set_master(pdev); ++ ++ err = -ENOMEM; ++ netdev = alloc_etherdev(sizeof(struct iegbe_adapter)); ++ if (!netdev) ++ goto err_alloc_etherdev; + +- SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + +- pci_set_drvdata(pdev, netdev); +- adapter = netdev_priv(netdev); +- adapter->netdev = netdev; +- adapter->pdev = pdev; +- adapter->hw.back = adapter; +- adapter->msg_enable = (0x1 << debug) - 0x1; +- +- mmio_start = pci_resource_start(pdev, BAR_0); +- mmio_len = pci_resource_len(pdev, BAR_0); +- +- adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); +- if(!adapter->hw.hw_addr) { +- err = -EIO; +- goto err_ioremap; +- } +- +- for(i = BAR_1; i <= BAR_5; i++) { +- if(pci_resource_len(pdev, i) == 0) { +- continue; +- } +- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) { +- adapter->hw.io_base = pci_resource_start(pdev, i); +- break; +- } +- } +- +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_multicast_list = &iegbe_set_multi; ++ pci_set_drvdata(pdev, netdev); ++ adapter = netdev_priv(netdev); ++ adapter->netdev = netdev; ++ adapter->pdev = pdev; ++ adapter->msg_enable = (1 << debug) - 1; ++ adapter->bars = bars; ++ ++ hw = &adapter->hw; ++ hw->back = adapter; ++ ++ err = -EIO; ++ hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0), ++ pci_resource_len(pdev, BAR_0)); ++ if (!hw->hw_addr) ++ goto err_ioremap; ++ ++ netdev->open = &iegbe_open; ++ netdev->stop = &iegbe_close; ++ netdev->hard_start_xmit = &iegbe_xmit_frame; ++ netdev->get_stats = &iegbe_get_stats; ++ netdev->set_rx_mode = &iegbe_set_rx_mode; + netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->change_mtu = &iegbe_change_mtu; ++ netdev->do_ioctl = &iegbe_ioctl; + set_ethtool_ops(netdev); +-#ifdef HAVE_TX_TIMEOUT +- netdev->tx_timeout = &iegbe_tx_timeout; +- netdev->watchdog_timeo = 0x5 * HZ; +-#endif +-#ifdef CONFIG_E1000_NAPI +- netdev->poll = &iegbe_clean; +- netdev->weight = 0x40; +-#endif +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#endif ++ netdev->tx_timeout = &iegbe_tx_timeout; ++ netdev->watchdog_timeo = 5 * HZ; ++ netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); ++ netdev->vlan_rx_register = iegbe_vlan_rx_register; ++ netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; ++ netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; + #ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; ++ netdev->poll_controller = iegbe_netpoll; + #endif +- strcpy(netdev->name, pci_name(pdev)); ++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + +- netdev->mem_start = mmio_start; +- netdev->mem_end = mmio_start + mmio_len; +- netdev->base_addr = adapter->hw.io_base; + +- adapter->bd_number = cards_found; ++ adapter->bd_number = cards_found; + +- /* setup the private structure */ ++ /* setup the private structure */ + +- if((err = iegbe_sw_init(adapter))) { +- goto err_sw_init; +- } +- if((err = iegbe_check_phy_reset_block(&adapter->hw))) { +- DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); +- } +-#ifdef MAX_SKB_FRAGS +- if(adapter->hw.mac_type >= iegbe_82543) { +-#ifdef NETIF_F_HW_VLAN_TX +- netdev->features = NETIF_F_SG | +- NETIF_F_HW_CSUM | +- NETIF_F_HW_VLAN_TX | +- NETIF_F_HW_VLAN_RX | +- NETIF_F_HW_VLAN_FILTER; +-#else +- netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM; +-#endif +- } ++ err = iegbe_sw_init(adapter); ++ if (err) ++ goto err_sw_init; ++ err = -EIO; ++ if (iegbe_check_phy_reset_block(hw)) ++ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); + +-#ifdef NETIF_F_TSO +- if((adapter->hw.mac_type >= iegbe_82544) && +- (adapter->hw.mac_type != iegbe_82547)) { +- netdev->features |= NETIF_F_TSO; +- } +-#ifdef NETIF_F_TSO_IPV6 +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- netdev->features |= NETIF_F_TSO_IPV6; +- } +-#endif +-#endif +- if(pci_using_dac) { +- netdev->features |= NETIF_F_HIGHDMA; ++ if (hw->mac_type >= iegbe_82543) { ++ netdev->features = NETIF_F_SG | ++ NETIF_F_HW_CSUM | ++ NETIF_F_HW_VLAN_TX | ++ NETIF_F_HW_VLAN_RX | ++ NETIF_F_HW_VLAN_FILTER; + } +-#endif +-#ifdef NETIF_F_LLTX +- netdev->features |= NETIF_F_LLTX; +-#endif + +- adapter->en_mng_pt = iegbe_enable_mng_pass_thru(&adapter->hw); ++ if ((hw->mac_type >= iegbe_82544) && ++ (hw->mac_type != iegbe_82547)) ++ netdev->features |= NETIF_F_TSO; + +- /* before reading the EEPROM, reset the controller to +- * put the device in a known good starting state */ ++ if (hw->mac_type > iegbe_82547_rev_2) ++ netdev->features |= NETIF_F_TSO6; ++ if (pci_using_dac) ++ netdev->features |= NETIF_F_HIGHDMA; ++ ++ netdev->features |= NETIF_F_LLTX; + +- iegbe_reset_hw(&adapter->hw); ++ adapter->en_mng_pt = iegbe_enable_mng_pass_thru(hw); + +- /* make sure the EEPROM is good */ +- if(iegbe_validate_eeprom_checksum(&adapter->hw) < 0) { +- DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); +- err = -EIO; ++ /* initialize eeprom parameters */ ++ ++ if (iegbe_init_eeprom_params(hw)) { ++ E1000_ERR("EEPROM initialization failed\n"); + goto err_eeprom; + } + +- /* copy the MAC address out of the EEPROM */ ++ /* before reading the EEPROM, reset the controller to ++ * put the device in a known good starting state */ + +- if(iegbe_read_mac_addr(&adapter->hw)) { +- DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); +- } +- memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); ++ iegbe_reset_hw(hw); + +- if(!is_valid_ether_addr(netdev->dev_addr)) { +- DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); +- err = -EIO; +- goto err_eeprom; +- } ++ /* make sure the EEPROM is good */ ++ if (iegbe_validate_eeprom_checksum(hw) < 0) { ++ DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); ++ iegbe_dump_eeprom(adapter); ++ /* ++ * set MAC address to all zeroes to invalidate and temporary ++ * disable this device for the user. This blocks regular ++ * traffic while still permitting ethtool ioctls from reaching ++ * the hardware as well as allowing the user to run the ++ * interface after manually setting a hw addr using ++ * `ip set address` ++ */ ++ memset(hw->mac_addr, 0, netdev->addr_len); ++ } else { ++ /* copy the MAC address out of the EEPROM */ ++ if (iegbe_read_mac_addr(hw)) ++ DPRINTK(PROBE, ERR, "EEPROM Read Error\n"); ++ } ++ /* don't block initalization here due to bad MAC address */ ++ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); ++ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len); + +- iegbe_read_part_num(&adapter->hw, &(adapter->part_num)); ++ if (!is_valid_ether_addr(netdev->perm_addr)) ++ DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); + +- iegbe_get_bus_info(&adapter->hw); ++ iegbe_get_bus_info(hw); + + init_timer(&adapter->tx_fifo_stall_timer); + adapter->tx_fifo_stall_timer.function = &iegbe_82547_tx_fifo_stall; +- adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; ++ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter; + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &iegbe_watchdog; +@@ -906,75 +902,50 @@ iegbe_probe(struct pci_dev *pdev, + + init_timer(&adapter->phy_info_timer); + adapter->phy_info_timer.function = &iegbe_update_phy_info; +- adapter->phy_info_timer.data = (unsigned long) adapter; +- +- INIT_WORK(&adapter->tx_timeout_task, +- (void (*)(void *))iegbe_tx_timeout_task, netdev); ++ adapter->phy_info_timer.data = (unsigned long)adapter; + +- /* we're going to reset, so assume we have no link for now */ +- +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); ++ INIT_WORK(&adapter->reset_task, iegbe_reset_task); + +- iegbe_check_options(adapter); ++ iegbe_check_options(adapter); + +- /* Initial Wake on LAN setting +- * If APM wake is enabled in the EEPROM, +- * enable the ACPI Magic Packet filter +- */ ++ /* Initial Wake on LAN setting ++ * If APM wake is enabled in the EEPROM, ++ * enable the ACPI Magic Packet filter ++ */ + +- switch(adapter->hw.mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- case iegbe_82543: +- break; +- case iegbe_82544: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); +- eeprom_apme_mask = E1000_EEPROM_82544_APM; +- break; ++ switch(adapter->hw.mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ case iegbe_82543: ++ break; ++ case iegbe_82544: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); ++ eeprom_apme_mask = E1000_EEPROM_82544_APM; ++ break; + case iegbe_icp_xxxx: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), +- 1, &eeprom_data); +- eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; +- break; +- case iegbe_82546: +- case iegbe_82546_rev_3: +- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) +- && (adapter->hw.media_type == iegbe_media_type_copper)) { +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); +- break; +- } +- /* Fall Through */ +- default: +- iegbe_read_eeprom(&adapter->hw, +- EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); +- break; +- } ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_ICP_xxxx(adapter->bd_number), ++ 1, &eeprom_data); ++ eeprom_apme_mask = EEPROM_CTRL3_APME_ICP_xxxx; ++ break; ++ case iegbe_82546: ++ case iegbe_82546_rev_3: ++ if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) ++ && (adapter->hw.media_type == iegbe_media_type_copper)) { ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); ++ break; ++ } ++ /* Fall Through */ ++ default: ++ iegbe_read_eeprom(&adapter->hw, ++ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); ++ break; ++ } + if(eeprom_data & eeprom_apme_mask) { +- adapter->wol |= E1000_WUFC_MAG; ++ adapter->wol |= E1000_WUFC_MAG; + } +- /* reset the hardware with the new settings */ +- iegbe_reset(adapter); +- +- /* Let firmware know the driver has taken over */ +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } + + /* The ICP_xxxx device has multiple, duplicate interrupt + * registers, so disable all but the first one +@@ -987,24 +958,40 @@ iegbe_probe(struct pci_dev *pdev, + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + } + +- strcpy(netdev->name, "eth%d"); +- if((err = register_netdev(netdev))) { +- goto err_register; +- } ++ iegbe_reset(adapter); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ strcpy(netdev->name, "eth%d"); ++ err = register_netdev(netdev); ++ if (err) ++ goto err_register; ++ + DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n"); + +- cards_found++; +- return 0; ++ cards_found++; ++ return 0; + + err_register: +-err_sw_init: + err_eeprom: +- iounmap(adapter->hw.hw_addr); ++ if (!iegbe_check_phy_reset_block(hw)) ++ iegbe_phy_hw_reset(hw); ++ if (hw->flash_address) ++ iounmap(hw->flash_address); ++ for (i = 0; i < adapter->num_rx_queues; i++) ++ dev_put(&adapter->polling_netdev[i]); ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); ++err_sw_init: ++ iounmap(hw->hw_addr); + err_ioremap: +- free_netdev(netdev); ++ free_netdev(netdev); + err_alloc_etherdev: +- pci_release_regions(pdev); +- return err; ++ pci_release_selected_regions(pdev, bars); ++err_pci_reg: ++err_dma: ++ pci_disable_device(pdev); ++ return err; + } + + /** +@@ -1020,64 +1007,36 @@ err_alloc_etherdev: + static void __devexit + iegbe_remove(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl_ext; +- uint32_t manc, swsm; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } +- } +- +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- +- default: +- break; +- } ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc; ++ int i; ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ } + +- unregister_netdev(netdev); +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) ++ unregister_netdev(netdev); ++ for (i = 0x0; i < adapter->num_rx_queues; i++) + dev_put(&adapter->polling_netdev[i]); +-#endif + + if(!iegbe_check_phy_reset_block(&adapter->hw)) { +- iegbe_phy_hw_reset(&adapter->hw); ++ iegbe_phy_hw_reset(&adapter->hw); + } +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +-#ifdef CONFIG_E1000_NAPI +- kfree(adapter->polling_netdev); +-#endif ++ kfree(adapter->tx_ring); ++ kfree(adapter->rx_ring); ++ kfree(adapter->polling_netdev); + +- iounmap(adapter->hw.hw_addr); +- pci_release_regions(pdev); ++ iounmap(adapter->hw.hw_addr); ++ pci_release_regions(pdev); + +-#ifdef CONFIG_E1000_MQ +- free_percpu(adapter->cpu_netdev); +- free_percpu(adapter->cpu_tx_ring); +-#endif +- free_netdev(netdev); ++ free_netdev(netdev); + } + + /** +@@ -1092,118 +1051,78 @@ iegbe_remove(struct pci_dev *pdev) + static int __devinit + iegbe_sw_init(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +-#ifdef CONFIG_E1000_NAPI +- int i; +-#endif ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ int i; + +- /* PCI config space info */ ++ /* PCI config space info */ + +- hw->vendor_id = pdev->vendor; +- hw->device_id = pdev->device; +- hw->subsystem_vendor_id = pdev->subsystem_vendor; +- hw->subsystem_id = pdev->subsystem_device; ++ hw->vendor_id = pdev->vendor; ++ hw->device_id = pdev->device; ++ hw->subsystem_vendor_id = pdev->subsystem_vendor; ++ hw->subsystem_id = pdev->subsystem_device; + +- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); ++ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + +- pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); ++ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); + +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; +- hw->max_frame_size = netdev->mtu + +- ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; +- hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256; ++ hw->max_frame_size = netdev->mtu + ++ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; + +- /* identify the MAC */ ++ /* identify the MAC */ + +- if(iegbe_set_mac_type(hw)) { ++ if (iegbe_set_mac_type(hw)) { + DPRINTK(PROBE, ERR, "Unknown MAC Type\n"); + return -EIO; + } + +- /* initialize eeprom parameters */ +- +- if(iegbe_init_eeprom_params(hw)) { +- E1000_ERR("EEPROM initialization failed\n"); +- return -EIO; +- } +- +- switch(hw->mac_type) { +- default: +- break; +- case iegbe_82541: +- case iegbe_82547: +- case iegbe_82541_rev_2: +- case iegbe_82547_rev_2: +- hw->phy_init_script = 0x1; +- break; +- } +- +- iegbe_set_media_type(hw); ++ iegbe_set_media_type(hw); + +- hw->wait_autoneg_complete = FALSE; +- hw->tbi_compatibility_en = TRUE; +- hw->adaptive_ifs = TRUE; ++ hw->wait_autoneg_complete = FALSE; ++ hw->tbi_compatibility_en = TRUE; ++ hw->adaptive_ifs = TRUE; + +- /* Copper options */ ++ /* Copper options */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- hw->mdix = AUTO_ALL_MODES; +- hw->disable_polarity_correction = FALSE; +- hw->master_slave = E1000_MASTER_SLAVE; +- } ++ hw->mdix = AUTO_ALL_MODES; ++ hw->disable_polarity_correction = FALSE; ++ hw->master_slave = E1000_MASTER_SLAVE; ++ } + +-#ifdef CONFIG_E1000_MQ +- /* Number of supported queues */ +- switch (hw->mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- adapter->num_queues = 0x2; +- break; +- default: +- adapter->num_queues = 0x1; +- break; +- } +- adapter->num_queues = min(adapter->num_queues, num_online_cpus()); +-#else +- adapter->num_queues = 0x1; +-#endif ++ adapter->num_tx_queues = 0x1; ++ adapter->num_rx_queues = 0x1; + + if (iegbe_alloc_queues(adapter)) { + DPRINTK(PROBE, ERR, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + +-#ifdef CONFIG_E1000_NAPI +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + adapter->polling_netdev[i].priv = adapter; +- adapter->polling_netdev[i].poll = &iegbe_clean; +- adapter->polling_netdev[i].weight = 0x40; + dev_hold(&adapter->polling_netdev[i]); + set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); + } +-#endif +- +-#ifdef CONFIG_E1000_MQ +- iegbe_setup_queue_mapping(adapter); +-#endif ++ spin_lock_init(&adapter->tx_queue_lock); + + /* +- * for ICP_XXXX style controllers, it is necessary to keep +- * track of the last known state of the link to determine if +- * the link experienced a change in state when iegbe_watchdog +- * fires +- */ +- adapter->hw.icp_xxxx_is_link_up = FALSE; ++ * for ICP_XXXX style controllers, it is necessary to keep ++ * track of the last known state of the link to determine if ++ * the link experienced a change in state when iegbe_watchdog ++ * fires ++ */ ++ adapter->hw.icp_xxxx_is_link_up = FALSE; + +- atomic_set(&adapter->irq_sem, 1); +- spin_lock_init(&adapter->stats_lock); ++ spin_lock_init(&adapter->stats_lock); + +- return 0; ++ set_bit(__E1000_DOWN, &adapter->flags); ++ return 0x0; + } + + /** +@@ -1218,71 +1137,31 @@ iegbe_sw_init(struct iegbe_adapter *adap + static int __devinit + iegbe_alloc_queues(struct iegbe_adapter *adapter) + { +- int size; + +- size = sizeof(struct iegbe_tx_ring) * adapter->num_queues; +- adapter->tx_ring = kmalloc(size, GFP_KERNEL); +- if (!adapter->tx_ring){ ++ ++ adapter->tx_ring = kcalloc(adapter->num_tx_queues, ++ sizeof(struct iegbe_tx_ring), GFP_KERNEL); ++ if (!adapter->tx_ring) + return -ENOMEM; +- } +- memset(adapter->tx_ring, 0, size); + +- size = sizeof(struct iegbe_rx_ring) * adapter->num_queues; +- adapter->rx_ring = kmalloc(size, GFP_KERNEL); ++ adapter->rx_ring = kcalloc(adapter->num_rx_queues, ++ sizeof(struct iegbe_rx_ring), GFP_KERNEL); + if (!adapter->rx_ring) { + kfree(adapter->tx_ring); + return -ENOMEM; + } +- memset(adapter->rx_ring, 0, size); + +-#ifdef CONFIG_E1000_NAPI +- size = sizeof(struct net_device) * adapter->num_queues; +- adapter->polling_netdev = kmalloc(size, GFP_KERNEL); ++ adapter->polling_netdev = kcalloc(adapter->num_rx_queues, ++ sizeof(struct net_device), ++ GFP_KERNEL); + if (!adapter->polling_netdev) { + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + return -ENOMEM; + } +- memset(adapter->polling_netdev, 0, size); +-#endif +- +- return E1000_SUCCESS; +-} + +-#ifdef CONFIG_E1000_MQ +-static void __devinit +-iegbe_setup_queue_mapping(struct iegbe_adapter *adapter) +-{ +- int i, cpu; +- +- adapter->rx_sched_call_data.func = iegbe_rx_schedule; +- adapter->rx_sched_call_data.info = adapter->netdev; +- cpus_clear(adapter->rx_sched_call_data.cpumask); +- +- adapter->cpu_netdev = alloc_percpu(struct net_device *); +- adapter->cpu_tx_ring = alloc_percpu(struct iegbe_tx_ring *); +- +- lock_cpu_hotplug(); +- i = 0; +- for_each_online_cpu(cpu) { +- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = +- &adapter->tx_ring[i % adapter->num_queues]; +- /* This is incomplete because we'd like to assign separate +- * physical cpus to these netdev polling structures and +- * avoid saturating a subset of cpus. +- */ +- if (i < adapter->num_queues) { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = +- &adapter->polling_netdev[i]; +- adapter->cpu_for_queue[i] = cpu; +- } else { +- *per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL; +- } +- i++; +- } +- unlock_cpu_hotplug(); ++ return E1000_SUCCESS; + } +-#endif + + /** + * iegbe_open - Called when a network interface is made active +@@ -1300,40 +1179,62 @@ iegbe_setup_queue_mapping(struct iegbe_a + static int + iegbe_open(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int err; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int err; ++ + ++ /* allocate receive descriptors */ ++ if (test_bit(__E1000_TESTING, &adapter->flags)) ++ return -EBUSY; + +- /* allocate receive descriptors */ ++ /* allocate transmit descriptors */ ++ err = iegbe_setup_all_tx_resources(adapter); ++ if (err) ++ goto err_setup_tx; + +- if ((err = iegbe_setup_all_rx_resources(adapter))) { ++ err = iegbe_setup_all_rx_resources(adapter); ++ if (err) + goto err_setup_rx; +- } +- /* allocate transmit descriptors */ +- if ((err = iegbe_setup_all_tx_resources(adapter))) { +- goto err_setup_tx; +- } +- if ((err = iegbe_up(adapter))) { +- goto err_up; +- } +-#ifdef NETIF_F_HW_VLAN_TX +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- if ((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { +- iegbe_update_mng_vlan(adapter); +- } +-#endif + +- return E1000_SUCCESS; ++ iegbe_power_up_phy(adapter); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ iegbe_update_mng_vlan(adapter); ++ } ++ ++ /* before we allocate an interrupt, we must be ready to handle it. ++ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt ++ * as soon as we call pci_request_irq, so we have to setup our ++ * clean_rx handler before we do so. */ ++ iegbe_configure(adapter); ++ err = iegbe_request_irq(adapter); ++ if (err) ++ goto err_req_irq; + +-err_up: +- iegbe_free_all_tx_resources(adapter); +-err_setup_tx: +- iegbe_free_all_rx_resources(adapter); ++ /* From here on the code is the same as iegbe_up() */ ++ clear_bit(__E1000_DOWN, &adapter->flags); ++ ++ napi_enable(&adapter->napi); ++ ++ iegbe_irq_enable(adapter); ++ ++ netif_start_queue(netdev); ++ ++ /* fire a link status change interrupt to start the watchdog */ ++ ++ return E1000_SUCCESS; ++ ++err_req_irq: ++ iegbe_power_down_phy(adapter); ++ iegbe_free_all_rx_resources(adapter); + err_setup_rx: +- iegbe_reset(adapter); ++ iegbe_free_all_tx_resources(adapter); ++err_setup_tx: ++ iegbe_reset(adapter); + +- return err; ++ return err; + } + + /** +@@ -1348,22 +1249,25 @@ err_setup_rx: + * hardware, and all transmit and receive resources are freed. + **/ + +-static int +-iegbe_close(struct net_device *netdev) ++static int iegbe_close(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- +- iegbe_down(adapter); +- +- iegbe_free_all_tx_resources(adapter); +- iegbe_free_all_rx_resources(adapter); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + +-#ifdef NETIF_F_HW_VLAN_TX +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); ++ iegbe_power_down_phy(adapter); ++ iegbe_free_irq(adapter); ++ ++ iegbe_free_all_tx_resources(adapter); ++ iegbe_free_all_rx_resources(adapter); ++ ++ if ((hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ !(adapter->vlgrp && ++ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) { + iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + } +-#endif + return 0; + } + +@@ -1375,19 +1279,19 @@ iegbe_close(struct net_device *netdev) + **/ + static inline boolean_t + iegbe_check_64k_bound(struct iegbe_adapter *adapter, +- void *start, unsigned long len) ++ void *start, unsigned long len) + { +- unsigned long begin = (unsigned long) start; +- unsigned long end = begin + len; ++ unsigned long begin = (unsigned long) start; ++ unsigned long end = begin + len; + +- /* First rev 82545 and 82546 need to not allow any memory +- * write location to cross 64k boundary due to errata 23 */ +- if(adapter->hw.mac_type == iegbe_82545 || +- adapter->hw.mac_type == iegbe_82546) { +- return ((begin ^ (end - 1)) >> 0x10) != 0 ? FALSE : TRUE; +- } ++ /* First rev 82545 and 82546 need to not allow any memory ++ * write location to cross 64k boundary due to errata 23 */ ++ if(adapter->hw.mac_type == iegbe_82545 || ++ adapter->hw.mac_type == iegbe_82546) { ++ return ((begin ^ (end - 1)) >> 0x10) != 0x0 ? FALSE : TRUE; ++ } + +- return TRUE; ++ return TRUE; + } + + /** +@@ -1398,102 +1302,98 @@ iegbe_check_64k_bound(struct iegbe_adapt + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_tx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *txdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size; ++ struct pci_dev *pdev = adapter->pdev; ++ int size; + +- size = sizeof(struct iegbe_buffer) * txdr->count; +- txdr->buffer_info = vmalloc(size); +- if (!txdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } ++ size = sizeof(struct iegbe_buffer) * txdr->count; ++ txdr->buffer_info = vmalloc(size); ++ if (!txdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } + memset(txdr->buffer_info, 0, size); +- memset(&txdr->previous_buffer_info, 0, sizeof(struct iegbe_buffer)); + +- /* round up to nearest 4K */ ++ /* round up to nearest 4K */ + +- txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); +- E1000_ROUNDUP(txdr->size, 0x1000); ++ txdr->size = txdr->count * sizeof(struct iegbe_tx_desc); ++ txdr->size = ALIGN(txdr->size, 4096); + +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- if (!txdr->desc) { ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ if (!txdr->desc) { + setup_tx_desc_die: +- vfree(txdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the transmit descriptor ring\n"); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- void *olddesc = txdr->desc; +- dma_addr_t olddma = txdr->dma; +- DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " +- "at %p\n", txdr->size, txdr->desc); +- /* Try again, without freeing the previous */ +- txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); +- /* Failed allocation, critical failure */ +- if (!txdr->desc) { +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- goto setup_tx_desc_die; +- } ++ vfree(txdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the transmit descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ void *olddesc = txdr->desc; ++ dma_addr_t olddma = txdr->dma; ++ DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes " ++ "at %p\n", txdr->size, txdr->desc); ++ /* Try again, without freeing the previous */ ++ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!txdr->desc) { ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ goto setup_tx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, txdr->size, txdr->desc, +- txdr->dma); +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the transmit descriptor ring\n"); +- vfree(txdr->buffer_info); +- return -ENOMEM; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, txdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, txdr->desc, txdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, txdr->size, txdr->desc, ++ txdr->dma); ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the transmit descriptor ring\n"); ++ vfree(txdr->buffer_info); ++ return -ENOMEM; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, txdr->size, olddesc, olddma); ++ } ++ } + memset(txdr->desc, 0, txdr->size); + + txdr->next_to_use = 0; + txdr->next_to_clean = 0; +- spin_lock_init(&txdr->tx_lock); ++ spin_lock_init(&txdr->tx_lock); + + return 0; + } + + /** + * iegbe_setup_all_tx_resources - wrapper to allocate Tx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * +- * If this function returns with an error, then it's possible one or +- * more of the rings is populated (while the rest are not). It is the +- * callers duty to clean those orphaned rings. +- * + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_tx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_tx_queues; i++) { + err = iegbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Tx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_tx_resources(adapter, ++ &adapter->tx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1512,113 +1412,108 @@ iegbe_configure_tx(struct iegbe_adapter + + /* Setup the HW Tx Head and Tail descriptor pointers */ + +- switch (adapter->num_queues) { ++ switch (adapter->num_tx_queues) { + case 0x2: + tdba = adapter->tx_ring[0x1].dma; + tdlen = adapter->tx_ring[0x1].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL1, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH1, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN1, tdlen); +- E1000_WRITE_REG(hw, TDH1, 0); +- E1000_WRITE_REG(hw, TDT1, 0); ++ E1000_WRITE_REG(hw, TDLEN1, tdlen); ++ E1000_WRITE_REG(hw, TDH1, 0x0); ++ E1000_WRITE_REG(hw, TDT1, 0x0); + adapter->tx_ring[0x1].tdh = E1000_TDH1; + adapter->tx_ring[0x1].tdt = E1000_TDT1; +- /* Fall Through */ ++ /* Fall Through */ + case 0x1: +- default: +- tdba = adapter->tx_ring[0].dma; +- tdlen = adapter->tx_ring[0].count * +- sizeof(struct iegbe_tx_desc); +- E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); ++ default: ++ tdba = adapter->tx_ring[0x0].dma; ++ tdlen = adapter->tx_ring[0x0].count * ++ sizeof(struct iegbe_tx_desc); ++ E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, TDBAH, (tdba >> 0x20)); +- E1000_WRITE_REG(hw, TDLEN, tdlen); +- E1000_WRITE_REG(hw, TDH, 0); +- E1000_WRITE_REG(hw, TDT, 0); +- adapter->tx_ring[0].tdh = E1000_TDH; +- adapter->tx_ring[0].tdt = E1000_TDT; +- break; +- } +- +- /* Set the default values for the Tx Inter Packet Gap timer */ +- +- switch (hw->mac_type) { +- case iegbe_82542_rev2_0: +- case iegbe_82542_rev2_1: +- tipg = DEFAULT_82542_TIPG_IPGT; +- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- break; +- default: +- switch(hw->media_type) { +- case iegbe_media_type_fiber: +- case iegbe_media_type_internal_serdes: +- tipg = DEFAULT_82543_TIPG_IPGT_FIBER; +- break; +- case iegbe_media_type_copper: +- tipg = DEFAULT_82543_TIPG_IPGT_COPPER; +- break; +- case iegbe_media_type_oem: +- default: ++ E1000_WRITE_REG(hw, TDLEN, tdlen); ++ E1000_WRITE_REG(hw, TDH, 0x0); ++ E1000_WRITE_REG(hw, TDT, 0x0); ++ adapter->tx_ring[0x0].tdh = E1000_TDH; ++ adapter->tx_ring[0x0].tdt = E1000_TDT; ++ break; ++ } ++ ++ /* Set the default values for the Tx Inter Packet Gap timer */ ++ ++ switch (hw->mac_type) { ++ case iegbe_82542_rev2_0: ++ case iegbe_82542_rev2_1: ++ tipg = DEFAULT_82542_TIPG_IPGT; ++ tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ break; ++ default: ++ switch(hw->media_type) { ++ case iegbe_media_type_fiber: ++ case iegbe_media_type_internal_serdes: ++ tipg = DEFAULT_82543_TIPG_IPGT_FIBER; ++ break; ++ case iegbe_media_type_copper: ++ tipg = DEFAULT_82543_TIPG_IPGT_COPPER; ++ break; ++ case iegbe_media_type_oem: ++ default: + tipg = (0xFFFFFFFFUL >> (sizeof(tipg)*0x8 - + E1000_TIPG_IPGR1_SHIFT)) +- & iegbe_oem_get_tipg(&adapter->hw); +- break; +- } +- tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; +- tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; +- } +- E1000_WRITE_REG(hw, TIPG, tipg); ++ & iegbe_oem_get_tipg(&adapter->hw); ++ break; ++ } ++ tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; ++ tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; ++ } ++ E1000_WRITE_REG(hw, TIPG, tipg); + +- /* Set the Tx Interrupt Delay register */ ++ /* Set the Tx Interrupt Delay register */ + +- E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); ++ E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); + if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); ++ E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); + } +- /* Program the Transmit Control Register */ ++ /* Program the Transmit Control Register */ + +- tctl = E1000_READ_REG(hw, TCTL); ++ tctl = E1000_READ_REG(hw, TCTL); + +- tctl &= ~E1000_TCTL_CT; +- tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | +- (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); ++ tctl &= ~E1000_TCTL_CT; ++ tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | E1000_TCTL_RTLC | ++ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + +- E1000_WRITE_REG(hw, TCTL, tctl); ++ E1000_WRITE_REG(hw, TCTL, tctl); + +- if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { +- tarc = E1000_READ_REG(hw, TARC0); ++ if (hw->mac_type == iegbe_82571 || hw->mac_type == iegbe_82572) { ++ tarc = E1000_READ_REG(hw, TARC0); + tarc |= ((0x1 << 0x19) | (0x1 << 0x15)); +- E1000_WRITE_REG(hw, TARC0, tarc); +- tarc = E1000_READ_REG(hw, TARC1); ++ E1000_WRITE_REG(hw, TARC0, tarc); ++ tarc = E1000_READ_REG(hw, TARC1); + tarc |= (0x1 << 0x19); + if (tctl & E1000_TCTL_MULR) { + tarc &= ~(0x1 << 0x1c); + } else { + tarc |= (0x1 << 0x1c); + } +- E1000_WRITE_REG(hw, TARC1, tarc); +- } ++ E1000_WRITE_REG(hw, TARC1, tarc); ++ } + +- iegbe_config_collision_dist(hw); ++ iegbe_config_collision_dist(hw); + +- /* Setup Transmit Descriptor Settings for eop descriptor */ +- adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | +- E1000_TXD_CMD_IFCS; ++ /* Setup Transmit Descriptor Settings for eop descriptor */ ++ adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | ++ E1000_TXD_CMD_IFCS; + + if (hw->mac_type < iegbe_82543) { +- adapter->txd_cmd |= E1000_TXD_CMD_RPS; ++ adapter->txd_cmd |= E1000_TXD_CMD_RPS; + } else { +-#ifdef IEGBE_GBE_WORKAROUND +- /* Disable the RS bit in the Tx descriptor */ +- adapter->txd_cmd &= ~E1000_TXD_CMD_RS; +-#else +- adapter->txd_cmd |= E1000_TXD_CMD_RS; +-#endif ++ adapter->txd_cmd |= E1000_TXD_CMD_RS; + } +- /* Cache if we're 82544 running in PCI-X because we'll +- * need this to apply a workaround later in the send path. */ +- if (hw->mac_type == iegbe_82544 && ++ /* Cache if we're 82544 running in PCI-X because we'll ++ * need this to apply a workaround later in the send path. */ ++ if (hw->mac_type == iegbe_82544 && + hw->bus_type == iegbe_bus_type_pcix) { + adapter->pcix_82544 = 0x1; + } +@@ -1632,96 +1527,95 @@ iegbe_configure_tx(struct iegbe_adapter + * Returns 0 on success, negative on failure + **/ + +-int +-iegbe_setup_rx_resources(struct iegbe_adapter *adapter, ++static int iegbe_setup_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rxdr) + { +- struct pci_dev *pdev = adapter->pdev; +- int size, desc_len; +- +- size = sizeof(struct iegbe_buffer) * rxdr->count; +- rxdr->buffer_info = vmalloc(size); +- if (!rxdr->buffer_info) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->buffer_info, 0, size); +- +- size = sizeof(struct iegbe_ps_page) * rxdr->count; +- rxdr->ps_page = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page) { +- vfree(rxdr->buffer_info); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page, 0, size); +- +- size = sizeof(struct iegbe_ps_page_dma) * rxdr->count; +- rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL); +- if (!rxdr->ps_page_dma) { +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); +- return -ENOMEM; +- } +- memset(rxdr->ps_page_dma, 0, size); ++ struct iegbe_hw *hw = &adapter->hw; ++ struct pci_dev *pdev = adapter->pdev; ++ int size, desc_len; + +- if (adapter->hw.mac_type <= iegbe_82547_rev_2) { +- desc_len = sizeof(struct iegbe_rx_desc); +- } else { +- desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ size = sizeof(struct iegbe_buffer) * rxdr->count; ++ rxdr->buffer_info = vmalloc(size); ++ if (!rxdr->buffer_info) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; + } +- /* Round up to nearest 4K */ +- +- rxdr->size = rxdr->count * desc_len; +- E1000_ROUNDUP(rxdr->size, 0x1000); +- +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ memset(rxdr->buffer_info, 0, size); + +- if (!rxdr->desc) { +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory for the receive descriptor ring\n"); ++ rxdr->ps_page = kcalloc(rxdr->count, sizeof(struct iegbe_ps_page), ++ GFP_KERNEL); ++ if (!rxdr->ps_page) { ++ vfree(rxdr->buffer_info); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ rxdr->ps_page_dma = kcalloc(rxdr->count, ++ sizeof(struct iegbe_ps_page_dma), ++ GFP_KERNEL); ++ if (!rxdr->ps_page_dma) { ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); ++ return -ENOMEM; ++ } ++ ++ if (hw->mac_type <= iegbe_82547_rev_2) ++ desc_len = sizeof(struct iegbe_rx_desc); ++ else ++ desc_len = sizeof(union iegbe_rx_desc_packet_split); ++ ++ /* Round up to nearest 4K */ ++ ++ rxdr->size = rxdr->count * desc_len; ++ rxdr->size = ALIGN(rxdr->size, 4096); ++ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ ++ if (!rxdr->desc) { ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory for the receive descriptor ring\n"); + setup_rx_desc_die: +- vfree(rxdr->buffer_info); +- kfree(rxdr->ps_page); +- kfree(rxdr->ps_page_dma); +- return -ENOMEM; +- } +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- void *olddesc = rxdr->desc; +- dma_addr_t olddma = rxdr->dma; +- DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " +- "at %p\n", rxdr->size, rxdr->desc); +- /* Try again, without freeing the previous */ +- rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); +- /* Failed allocation, critical failure */ +- if (!rxdr->desc) { +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } ++ vfree(rxdr->buffer_info); ++ kfree(rxdr->ps_page); ++ kfree(rxdr->ps_page_dma); ++ return -ENOMEM; ++ } ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ void *olddesc = rxdr->desc; ++ dma_addr_t olddma = rxdr->dma; ++ DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes " ++ "at %p\n", rxdr->size, rxdr->desc); ++ /* Try again, without freeing the previous */ ++ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); ++ /* Failed allocation, critical failure */ ++ if (!rxdr->desc) { ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } + +- if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { +- /* give up */ +- pci_free_consistent(pdev, rxdr->size, rxdr->desc, +- rxdr->dma); +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- DPRINTK(PROBE, ERR, +- "Unable to allocate aligned memory " +- "for the receive descriptor ring\n"); +- goto setup_rx_desc_die; +- } else { +- /* Free old allocation, new allocation was successful */ +- pci_free_consistent(pdev, rxdr->size, olddesc, olddma); +- } +- } ++ if (!iegbe_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { ++ /* give up */ ++ pci_free_consistent(pdev, rxdr->size, rxdr->desc, ++ rxdr->dma); ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ DPRINTK(PROBE, ERR, ++ "Unable to allocate aligned memory " ++ "for the receive descriptor ring\n"); ++ goto setup_rx_desc_die; ++ } else { ++ /* Free old allocation, new allocation was successful */ ++ pci_free_consistent(pdev, rxdr->size, olddesc, olddma); ++ } ++ } + memset(rxdr->desc, 0, rxdr->size); + + rxdr->next_to_clean = 0; +@@ -1732,7 +1626,7 @@ setup_rx_desc_die: + + /** + * iegbe_setup_all_rx_resources - wrapper to allocate Rx resources +- * (Descriptors) for all queues ++ * (Descriptors) for all queues + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or +@@ -1742,21 +1636,23 @@ setup_rx_desc_die: + * Return 0 on success, negative on failure + **/ + +-int +-iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) ++int iegbe_setup_all_rx_resources(struct iegbe_adapter *adapter) + { + int i, err = 0; + +- for (i = 0; i < adapter->num_queues; i++) { ++ for (i = 0; i < adapter->num_rx_queues; i++) { + err = iegbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); + if (err) { + DPRINTK(PROBE, ERR, + "Allocation for Rx Queue %u failed\n", i); ++ for (i-- ; i >= 0; i--) ++ iegbe_free_rx_resources(adapter, ++ &adapter->rx_ring[i]); + break; + } + } + +- return err; ++ return err; + } + + /** +@@ -1765,105 +1661,104 @@ iegbe_setup_all_rx_resources(struct iegb + **/ + #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ + (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) +-static void +-iegbe_setup_rctl(struct iegbe_adapter *adapter) ++static void iegbe_setup_rctl(struct iegbe_adapter *adapter) + { +- uint32_t rctl, rfctl; +- uint32_t psrctl = 0; +-#ifdef CONFIG_E1000_PACKET_SPLIT +- uint32_t pages = 0; +-#endif +- +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- +- rctl &= ~(0x3 << E1000_RCTL_MO_SHIFT); +- +- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | +- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | +- (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); +- +- if(adapter->hw.tbi_compatibility_on == 0x1) { +- rctl |= E1000_RCTL_SBP; +- } else { +- rctl &= ~E1000_RCTL_SBP; +- } +- if(adapter->netdev->mtu <= ETH_DATA_LEN) { +- rctl &= ~E1000_RCTL_LPE; +- } else { +- rctl |= E1000_RCTL_LPE; +- } +- /* Setup buffer sizes */ +- if(adapter->hw.mac_type >= iegbe_82571) { +- /* We can now specify buffers in 1K increments. +- * BSIZE and BSEX are ignored in this case. */ +- rctl |= adapter->rx_buffer_len << 0x11; +- } else { +- rctl &= ~E1000_RCTL_SZ_4096; +- rctl |= E1000_RCTL_BSEX; +- switch (adapter->rx_buffer_len) { +- case E1000_RXBUFFER_2048: +- default: +- rctl |= E1000_RCTL_SZ_2048; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rctl, rfctl; ++ u32 psrctl = 0; ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ u32 pages = 0; ++#endif ++ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ ++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); ++ ++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | ++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | ++ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); ++ ++ if (hw->tbi_compatibility_on == 1) ++ rctl |= E1000_RCTL_SBP; ++ else ++ rctl &= ~E1000_RCTL_SBP; ++ ++ if (adapter->netdev->mtu <= ETH_DATA_LEN) ++ rctl &= ~E1000_RCTL_LPE; ++ else ++ rctl |= E1000_RCTL_LPE; ++ ++ /* Setup buffer sizes */ ++ /* We can now specify buffers in 1K increments. ++ * BSIZE and BSEX are ignored in this case. */ ++ rctl &= ~E1000_RCTL_SZ_4096; ++ rctl |= E1000_RCTL_BSEX; ++ switch (adapter->rx_buffer_len) { ++ case E1000_RXBUFFER_256: ++ rctl |= E1000_RCTL_SZ_256; + rctl &= ~E1000_RCTL_BSEX; + break; +- case E1000_RXBUFFER_4096: +- rctl |= E1000_RCTL_SZ_4096; +- break; +- case E1000_RXBUFFER_8192: +- rctl |= E1000_RCTL_SZ_8192; +- break; +- case E1000_RXBUFFER_16384: +- rctl |= E1000_RCTL_SZ_16384; +- break; +- } +- } ++ case E1000_RXBUFFER_2048: ++ default: ++ rctl |= E1000_RCTL_SZ_2048; ++ rctl &= ~E1000_RCTL_BSEX; ++ break; ++ case E1000_RXBUFFER_4096: ++ rctl |= E1000_RCTL_SZ_4096; ++ break; ++ case E1000_RXBUFFER_8192: ++ rctl |= E1000_RCTL_SZ_8192; ++ break; ++ case E1000_RXBUFFER_16384: ++ rctl |= E1000_RCTL_SZ_16384; ++ break; ++ } + +-#ifdef CONFIG_E1000_PACKET_SPLIT +- /* 82571 and greater support packet-split where the protocol +- * header is placed in skb->data and the packet data is +- * placed in pages hanging off of skb_shinfo(skb)->nr_frags. +- * In the case of a non-split, skb->data is linearly filled, +- * followed by the page buffers. Therefore, skb->data is +- * sized to hold the largest protocol header. +- */ +- pages = PAGE_USE_COUNT(adapter->netdev->mtu); +- if ((adapter->hw.mac_type > iegbe_82547_rev_2) && (pages <= 0x3) && +- PAGE_SIZE <= 0x4000) { +- adapter->rx_ps_pages = pages; +- } else { ++#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT ++ /* 82571 and greater support packet-split where the protocol ++ * header is placed in skb->data and the packet data is ++ * placed in pages hanging off of skb_shinfo(skb)->nr_frags. ++ * In the case of a non-split, skb->data is linearly filled, ++ * followed by the page buffers. Therefore, skb->data is ++ * sized to hold the largest protocol header. ++ */ ++ pages = PAGE_USE_COUNT(adapter->netdev->mtu); ++ if ((hw->mac_type >= iegbe_82571) && (pages <= 3) && ++ PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE)) ++ adapter->rx_ps_pages = pages; ++ else + adapter->rx_ps_pages = 0; +- } + #endif +- if (adapter->rx_ps_pages) { +- /* Configure extra packet-split registers */ +- rfctl = E1000_READ_REG(&adapter->hw, RFCTL); +- rfctl |= E1000_RFCTL_EXTEN; +- /* disable IPv6 packet split support */ +- rfctl |= E1000_RFCTL_IPV6_DIS; +- E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); +- +- rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC; +- +- psrctl |= adapter->rx_ps_bsize0 >> +- E1000_PSRCTL_BSIZE0_SHIFT; +- +- switch (adapter->rx_ps_pages) { +- case 0x3: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE3_SHIFT; +- case 0x2: +- psrctl |= PAGE_SIZE << +- E1000_PSRCTL_BSIZE2_SHIFT; +- case 0x1: +- psrctl |= PAGE_SIZE >> +- E1000_PSRCTL_BSIZE1_SHIFT; +- break; +- } ++ if (adapter->rx_ps_pages) { ++ /* Configure extra packet-split registers */ ++ rfctl = E1000_READ_REG(&adapter->hw, RFCTL); ++ rfctl |= E1000_RFCTL_EXTEN; ++ /* disable IPv6 packet split support */ ++ rfctl |= (E1000_RFCTL_IPV6_EX_DIS | ++ E1000_RFCTL_NEW_IPV6_EXT_DIS); ++ ++ rctl |= E1000_RCTL_DTYP_PS; ++ ++ psrctl |= adapter->rx_ps_bsize0 >> ++ E1000_PSRCTL_BSIZE0_SHIFT; ++ ++ switch (adapter->rx_ps_pages) { ++ case 3: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE3_SHIFT; ++ case 2: ++ psrctl |= PAGE_SIZE << ++ E1000_PSRCTL_BSIZE2_SHIFT; ++ case 1: ++ psrctl |= PAGE_SIZE >> ++ E1000_PSRCTL_BSIZE1_SHIFT; ++ break; ++ } + +- E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); +- } ++ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl); ++ } + +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + } + + /** +@@ -1873,145 +1768,87 @@ iegbe_setup_rctl(struct iegbe_adapter *a + * Configure the Rx unit of the MAC after a reset. + **/ + +-static void +-iegbe_configure_rx(struct iegbe_adapter *adapter) ++static void iegbe_configure_rx(struct iegbe_adapter *adapter) + { +- uint64_t rdba; +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rdlen, rctl, rxcsum, ctrl_ext; +-#ifdef CONFIG_E1000_MQ +- uint32_t reta, mrqc; +- int i; +-#endif ++ u64 rdba; ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 rdlen, rctl, rxcsum, ctrl_ext; + +- if (adapter->rx_ps_pages) { ++ if (adapter->rx_ps_pages) { + rdlen = adapter->rx_ring[0].count * +- sizeof(union iegbe_rx_desc_packet_split); +- adapter->clean_rx = iegbe_clean_rx_irq_ps; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; +- } else { ++ sizeof(union iegbe_rx_desc_packet_split); ++ adapter->clean_rx = iegbe_clean_rx_irq_ps; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers_ps; ++ } else { + rdlen = adapter->rx_ring[0].count * +- sizeof(struct iegbe_rx_desc); +- adapter->clean_rx = iegbe_clean_rx_irq; +- adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; +- } ++ sizeof(struct iegbe_rx_desc); ++ adapter->clean_rx = iegbe_clean_rx_irq; ++ adapter->alloc_rx_buf = iegbe_alloc_rx_buffers; ++ } + +- /* disable receives while setting up the descriptors */ +- rctl = E1000_READ_REG(hw, RCTL); +- E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); ++ /* disable receives while setting up the descriptors */ ++ rctl = E1000_READ_REG(hw, RCTL); ++ E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + +- /* set the Receive Delay Timer Register */ +- E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); ++ /* set the Receive Delay Timer Register */ ++ E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); + +- if (hw->mac_type >= iegbe_82540) { +- E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); +- if(adapter->itr > 0x1) { +- E1000_WRITE_REG(hw, ITR, +- 0x3b9aca00 / (adapter->itr * 0x100)); ++ if (hw->mac_type >= iegbe_82540) { ++ E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); ++ if (adapter->itr_setting != 0) ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (adapter->itr * 256)); + } +- } + +- if (hw->mac_type >= iegbe_82571) { +- /* Reset delay timers after every interrupt */ +- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_CANC; +- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); +- E1000_WRITE_FLUSH(hw); +- } ++ if (hw->mac_type >= iegbe_82571) { ++ /* Reset delay timers after every interrupt */ ++ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_CANC; ++ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); ++ E1000_WRITE_FLUSH(hw); ++ } + + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring */ +- switch (adapter->num_queues) { +-#ifdef CONFIG_E1000_MQ +- case 0x2: +- rdba = adapter->rx_ring[0x1].dma; +- E1000_WRITE_REG(hw, RDBAL1, (rdba & 0x00000000ffffffffULL)); +- E1000_WRITE_REG(hw, RDBAH1, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN1, rdlen); +- E1000_WRITE_REG(hw, RDH1, 0); +- E1000_WRITE_REG(hw, RDT1, 0); +- adapter->rx_ring[1].rdh = E1000_RDH1; +- adapter->rx_ring[1].rdt = E1000_RDT1; +- /* Fall Through */ +-#endif +- case 0x1: +- default: ++ switch (adapter->num_rx_queues) { ++ case 1: ++ default: + rdba = adapter->rx_ring[0].dma; +- E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); ++ E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); + E1000_WRITE_REG(hw, RDBAH, (rdba >> 0x20)); +- E1000_WRITE_REG(hw, RDLEN, rdlen); +- E1000_WRITE_REG(hw, RDH, 0); +- E1000_WRITE_REG(hw, RDT, 0); +- adapter->rx_ring[0].rdh = E1000_RDH; +- adapter->rx_ring[0].rdt = E1000_RDT; +- break; +- } ++ E1000_WRITE_REG(hw, RDLEN, rdlen); ++ adapter->rx_ring[0].rdh = ((hw->mac_type >= iegbe_82543) ? E1000_RDH : E1000_82542_RDH); ++ adapter->rx_ring[0].rdt = ((hw->mac_type >= iegbe_82543) ? E1000_RDT : E1000_82542_RDT); ++ break; ++ } + +-#ifdef CONFIG_E1000_MQ +- if (adapter->num_queues > 0x1) { +- uint32_t random[0xa]; +- +- get_random_bytes(&random[0], FORTY); +- +- if (hw->mac_type <= iegbe_82572) { +- E1000_WRITE_REG(hw, RSSIR, 0); +- E1000_WRITE_REG(hw, RSSIM, 0); +- } + +- switch (adapter->num_queues) { +- case 0x2: +- default: +- reta = 0x00800080; +- mrqc = E1000_MRQC_ENABLE_RSS_2Q; +- break; +- } +- +- /* Fill out redirection table */ +- for (i = 0; i < 0x20; i++) +- E1000_WRITE_REG_ARRAY(hw, RETA, i, reta); +- /* Fill out hash function seeds */ +- for (i = 0; i < 0xa; i++) +- E1000_WRITE_REG_ARRAY(hw, RSSRK, i, random[i]); +- +- mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 | +- E1000_MRQC_RSS_FIELD_IPV4_TCP); +- E1000_WRITE_REG(hw, MRQC, mrqc); +- } +- +- /* Multiqueue and packet checksumming are mutually exclusive. */ +- if (hw->mac_type >= iegbe_82571) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- rxcsum |= E1000_RXCSUM_PCSD; +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +- +-#else ++ /* Enable 82543 Receive Checksum Offload for TCP and UDP */ ++ if (hw->mac_type >= iegbe_82543) { ++ rxcsum = E1000_READ_REG(hw, RXCSUM); ++ if(adapter->rx_csum == TRUE) { ++ rxcsum |= E1000_RXCSUM_TUOFL; ++ ++ /* Enable 82571 IPv4 payload checksum for UDP fragments ++ * Must be used in conjunction with packet-split. */ ++ if ((hw->mac_type >= iegbe_82571) && ++ (adapter->rx_ps_pages)) { ++ rxcsum |= E1000_RXCSUM_IPPCSE; ++ } ++ } else { ++ rxcsum &= ~E1000_RXCSUM_TUOFL; ++ /* don't need to clear IPPCSE as it defaults to 0 */ ++ } ++ E1000_WRITE_REG(hw, RXCSUM, rxcsum); ++ } + +- /* Enable 82543 Receive Checksum Offload for TCP and UDP */ +- if (hw->mac_type >= iegbe_82543) { +- rxcsum = E1000_READ_REG(hw, RXCSUM); +- if(adapter->rx_csum == TRUE) { +- rxcsum |= E1000_RXCSUM_TUOFL; +- +- /* Enable 82571 IPv4 payload checksum for UDP fragments +- * Must be used in conjunction with packet-split. */ +- if ((hw->mac_type >= iegbe_82571) && +- (adapter->rx_ps_pages)) { +- rxcsum |= E1000_RXCSUM_IPPCSE; +- } +- } else { +- rxcsum &= ~E1000_RXCSUM_TUOFL; +- /* don't need to clear IPPCSE as it defaults to 0 */ +- } +- E1000_WRITE_REG(hw, RXCSUM, rxcsum); +- } +-#endif /* CONFIG_E1000_MQ */ ++ /* enable early receives on 82573, only takes effect if using > 2048 ++ * byte total frame size. for example only for jumbo frames */ ++#define E1000_ERT_2048 0x100 ++ if (hw->mac_type == iegbe_82573) ++ E1000_WRITE_REG(&adapter->hw, ERT, E1000_ERT_2048); + +- if (hw->mac_type == iegbe_82573) { +- E1000_WRITE_REG(hw, ERT, 0x0100); +- } + /* Enable Receives */ +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(hw, RCTL, rctl); + } + + /** +@@ -2022,20 +1859,19 @@ iegbe_configure_rx(struct iegbe_adapter + * Free all transmit software resources + **/ + +-void +-iegbe_free_tx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_tx_resources(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_tx_ring(adapter, tx_ring); ++ iegbe_clean_tx_ring(adapter, tx_ring); + +- vfree(tx_ring->buffer_info); +- tx_ring->buffer_info = NULL; ++ vfree(tx_ring->buffer_info); ++ tx_ring->buffer_info = NULL; + +- pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); ++ pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); + +- tx_ring->desc = NULL; ++ tx_ring->desc = NULL; + } + + /** +@@ -2048,85 +1884,29 @@ iegbe_free_tx_resources(struct iegbe_ada + void + iegbe_free_all_tx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0x0; i < adapter->num_tx_queues; i++) + iegbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + } + + static inline void + iegbe_unmap_and_free_tx_resource(struct iegbe_adapter *adapter, +- struct iegbe_buffer *buffer_info) +-{ +- if(buffer_info->dma) { +- pci_unmap_page(adapter->pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_TODEVICE); +- buffer_info->dma = 0; +- } +- if(buffer_info->skb) { +- dev_kfree_skb_any(buffer_info->skb); +- buffer_info->skb = NULL; +- } +-} +- +-#ifdef IEGBE_GBE_WORKAROUND +-/** +- * iegbe_clean_tx_ring_partial - Free Tx Buffers without using the DD +- * bit in the descriptor +- * @adapter: board private structure +- * @tx_ring: ring to be cleaned +- **/ +-static void iegbe_clean_tx_ring_partial(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) ++ struct iegbe_buffer *buffer_info) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_tx_desc *tx_desc; +- struct net_device *netdev = adapter->netdev; +- unsigned int i; +- unsigned tail; +- unsigned head; +- int cleaned = FALSE; +- +- tail = readl(adapter->hw.hw_addr + tx_ring->tdt); +- head = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (head != tail) { +- adapter->stats.tx_hnet++; +- } +- if (head != tx_ring->next_to_use) { +- adapter->stats.tx_hnentu++; +- } +- /* Free all the Tx ring sk_buffs from next_to_clean up until +- * the current head pointer +- */ +- i = tx_ring->next_to_clean; +- while(i != head) { +- cleaned = TRUE; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- +- tx_desc->upper.data = 0; +- +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- +- } +- tx_ring->next_to_clean = head; +- +- spin_lock(&tx_ring->tx_lock); +- +- /* Wake up the queue if it's currently stopped */ +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); ++ if(buffer_info->dma) { ++ pci_unmap_page(adapter->pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_TODEVICE); ++ buffer_info->dma = 0x0; ++ } ++ if(buffer_info->skb) { ++ dev_kfree_skb_any(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- +- spin_unlock(&tx_ring->tx_lock); + } +-#endif ++ + + /** + * iegbe_clean_tx_ring - Free Tx Buffers +@@ -2134,38 +1914,34 @@ static void iegbe_clean_tx_ring_partial( + * @tx_ring: ring to be cleaned + **/ + +-static void +-iegbe_clean_tx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_tx_ring(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct iegbe_buffer *buffer_info; +- unsigned long size; +- unsigned int i; +- +- /* Free all the Tx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned long size; ++ unsigned int i; + +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } ++ /* Free all the Tx ring sk_buffs */ + + for (i = 0; i < tx_ring->count; i++) { +- buffer_info = &tx_ring->buffer_info[i]; +- iegbe_unmap_and_free_tx_resource(adapter, buffer_info); +- } ++ buffer_info = &tx_ring->buffer_info[i]; ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); ++ } + +- size = sizeof(struct iegbe_buffer) * tx_ring->count; ++ size = sizeof(struct iegbe_buffer) * tx_ring->count; + memset(tx_ring->buffer_info, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; ++ tx_ring->last_tx_tso = 0; + +- writel(0, adapter->hw.hw_addr + tx_ring->tdh); +- writel(0, adapter->hw.hw_addr + tx_ring->tdt); ++ writel(0, hw->hw_addr + tx_ring->tdh); ++ writel(0, hw->hw_addr + tx_ring->tdt); + } + + /** +@@ -2173,12 +1949,11 @@ iegbe_clean_tx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_tx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + iegbe_clean_tx_ring(adapter, &adapter->tx_ring[i]); + } + +@@ -2190,24 +1965,23 @@ iegbe_clean_all_tx_rings(struct iegbe_ad + * Free all receive software resources + **/ + +-void +-iegbe_free_rx_resources(struct iegbe_adapter *adapter, ++static void iegbe_free_rx_resources(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct pci_dev *pdev = adapter->pdev; ++ struct pci_dev *pdev = adapter->pdev; + +- iegbe_clean_rx_ring(adapter, rx_ring); ++ iegbe_clean_rx_ring(adapter, rx_ring); + +- vfree(rx_ring->buffer_info); +- rx_ring->buffer_info = NULL; +- kfree(rx_ring->ps_page); +- rx_ring->ps_page = NULL; +- kfree(rx_ring->ps_page_dma); +- rx_ring->ps_page_dma = NULL; ++ vfree(rx_ring->buffer_info); ++ rx_ring->buffer_info = NULL; ++ kfree(rx_ring->ps_page); ++ rx_ring->ps_page = NULL; ++ kfree(rx_ring->ps_page_dma); ++ rx_ring->ps_page_dma = NULL; + +- pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); ++ pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); + +- rx_ring->desc = NULL; ++ rx_ring->desc = NULL; + } + + /** +@@ -2217,12 +1991,11 @@ iegbe_free_rx_resources(struct iegbe_ada + * Free all receive software resources + **/ + +-void +-iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) ++void iegbe_free_all_rx_resources(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + } + +@@ -2232,60 +2005,59 @@ iegbe_free_all_rx_resources(struct iegbe + * @rx_ring: ring to free buffers from + **/ + +-static void +-iegbe_clean_rx_ring(struct iegbe_adapter *adapter, ++static void iegbe_clean_rx_ring(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring) + { +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct pci_dev *pdev = adapter->pdev; +- unsigned long size; +- unsigned int i, j; +- +- /* Free all the Rx ring sk_buffs */ ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct pci_dev *pdev = adapter->pdev; ++ unsigned long size; ++ unsigned int i, j; ++ ++ /* Free all the Rx ring sk_buffs */ ++ ++ for (i = 0; i < rx_ring->count; i++) { ++ buffer_info = &rx_ring->buffer_info[i]; ++ if(buffer_info->skb) { ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); + +- for(i = 0; i < rx_ring->count; i++) { +- buffer_info = &rx_ring->buffer_info[i]; +- if(buffer_info->skb) { +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); +- +- dev_kfree_skb(buffer_info->skb); +- buffer_info->skb = NULL; +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!ps_page->ps_page[j]) { break; } +- pci_unmap_single(pdev, +- ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- put_page(ps_page->ps_page[j]); +- ps_page->ps_page[j] = NULL; +- } ++ dev_kfree_skb(buffer_info->skb); ++ buffer_info->skb = NULL; + } +- } ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ if (!ps_page->ps_page[j]) break; ++ pci_unmap_page(pdev, ++ ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ put_page(ps_page->ps_page[j]); ++ ps_page->ps_page[j] = NULL; ++ } ++ } + +- size = sizeof(struct iegbe_buffer) * rx_ring->count; ++ size = sizeof(struct iegbe_buffer) * rx_ring->count; + memset(rx_ring->buffer_info, 0, size); +- size = sizeof(struct iegbe_ps_page) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page) * rx_ring->count; + memset(rx_ring->ps_page, 0, size); +- size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; ++ size = sizeof(struct iegbe_ps_page_dma) * rx_ring->count; + memset(rx_ring->ps_page_dma, 0, size); + +- /* Zero out the descriptor ring */ ++ /* Zero out the descriptor ring */ + + memset(rx_ring->desc, 0, rx_ring->size); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + +- writel(0, adapter->hw.hw_addr + rx_ring->rdh); +- writel(0, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(0, hw->hw_addr + rx_ring->rdh); ++ writel(0, hw->hw_addr + rx_ring->rdt); + } + + /** +@@ -2293,60 +2065,54 @@ iegbe_clean_rx_ring(struct iegbe_adapter + * @adapter: board private structure + **/ + +-static void +-iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) ++static void iegbe_clean_all_rx_rings(struct iegbe_adapter *adapter) + { +- int i; ++ int i; + +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + iegbe_clean_rx_ring(adapter, &adapter->rx_ring[i]); + } + + /* The 82542 2.0 (revision 2) needs to have the receive unit in reset + * and memory write and invalidate disabled for certain operations + */ +-static void +-iegbe_enter_82542_rst(struct iegbe_adapter *adapter) ++static void iegbe_enter_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- iegbe_pci_clear_mwi(&adapter->hw); ++ iegbe_pci_clear_mwi(&adapter->hw); + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(netif_running(netdev)) { +- iegbe_clean_all_rx_rings(adapter); +-} ++ iegbe_clean_all_rx_rings(adapter); ++ } + } + + static void + iegbe_leave_82542_rst(struct iegbe_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- uint32_t rctl; ++ struct net_device *netdev = adapter->netdev; ++ uint32_t rctl; + +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_RST; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- E1000_WRITE_FLUSH(&adapter->hw); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_RST; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ E1000_WRITE_FLUSH(&adapter->hw); + mdelay(0x5); + + if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE) { +- iegbe_pci_set_mwi(&adapter->hw); ++ iegbe_pci_set_mwi(&adapter->hw); + } + if(netif_running(netdev)) { ++ struct iegbe_rx_ring *ring = &adapter->rx_ring[0x0]; + iegbe_configure_rx(adapter); +-#ifdef IEGBE_GBE_WORKAROUND +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0], +- IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS + 1); +-#else +- iegbe_alloc_rx_buffers(adapter, &adapter->rx_ring[0]); +-#endif ++ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); + } + } + +@@ -2358,133 +2124,153 @@ iegbe_leave_82542_rst(struct iegbe_adapt + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_set_mac(struct net_device *netdev, void *p) ++static int iegbe_set_mac(struct net_device *netdev, void *p) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct sockaddr *addr = p; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct sockaddr *addr = p; + + if(!is_valid_ether_addr(addr->sa_data)) { +- return -EADDRNOTAVAIL; ++ return -EADDRNOTAVAIL; + } +- /* 82542 2.0 needs to be in reset to write receive address registers */ ++ /* 82542 2.0 needs to be in reset to write receive address registers */ + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_enter_82542_rst(adapter); ++ iegbe_enter_82542_rst(adapter); + } +- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); +- memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); ++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); ++ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); + +- /* With 82571 controllers, LAA may be overwritten (with the default) +- * due to controller reset from the other port. */ +- if (adapter->hw.mac_type == iegbe_82571) { +- /* activate the work around */ ++ /* With 82571 controllers, LAA may be overwritten (with the default) ++ * due to controller reset from the other port. */ ++ if (adapter->hw.mac_type == iegbe_82571) { ++ /* activate the work around */ + adapter->hw.laa_is_present = 0x1; + +- /* Hold a copy of the LAA in RAR[14] This is done so that +- * between the time RAR[0] gets clobbered and the time it +- * gets fixed (in iegbe_watchdog), the actual LAA is in one +- * of the RARs and no incoming packets directed to this port +- * are dropped. Eventaully the LAA will be in RAR[0] and +- * RAR[14] */ +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, ++ /* Hold a copy of the LAA in RAR[14] This is done so that ++ * between the time RAR[0] gets clobbered and the time it ++ * gets fixed (in iegbe_watchdog), the actual LAA is in one ++ * of the RARs and no incoming packets directed to this port ++ * are dropped. Eventaully the LAA will be in RAR[0] and ++ * RAR[14] */ ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, + E1000_RAR_ENTRIES - 0x1); +- } ++ } + + if(adapter->hw.mac_type == iegbe_82542_rev2_0) { +- iegbe_leave_82542_rst(adapter); ++ iegbe_leave_82542_rst(adapter); + } +- return 0; ++ return 0x0; + } + + /** +- * iegbe_set_multi - Multicast and Promiscuous mode set ++ * iegbe_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set + * @netdev: network interface device structure + * +- * The set_multi entry point is called whenever the multicast address +- * list or the network interface flags are updated. This routine is +- * responsible for configuring the hardware for proper multicast, ++ * The set_rx_mode entry point is called whenever the unicast or multicast ++ * address lists or the network interface flags are updated. This routine is ++ * responsible for configuring the hardware for proper unicast, multicast, + * promiscuous mode, and all-multi behavior. + **/ + +-static void +-iegbe_set_multi(struct net_device *netdev) ++static void iegbe_set_rx_mode(struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_mc_list *mc_ptr; +- uint32_t rctl; +- uint32_t hash_value; ++ struct dev_addr_list *uc_ptr; ++ struct dev_addr_list *mc_ptr; ++ u32 rctl; ++ u32 hash_value; + int i, rar_entries = E1000_RAR_ENTRIES; ++int mta_reg_count = E1000_NUM_MTA_REGISTERS; + + /* reserve RAR[14] for LAA over-write work-around */ +- if (adapter->hw.mac_type == iegbe_82571) { ++ if (hw->mac_type == iegbe_82571) + rar_entries--; +- } ++ + /* Check for Promiscuous and All Multicast modes */ + +- rctl = E1000_READ_REG(hw, RCTL); ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); + + if (netdev->flags & IFF_PROMISC) { + rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); +- } else if (netdev->flags & IFF_ALLMULTI) { +- rctl |= E1000_RCTL_MPE; +- rctl &= ~E1000_RCTL_UPE; ++ rctl &= ~E1000_RCTL_VFE; + } else { +- rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); ++ if (netdev->flags & IFF_ALLMULTI) { ++ rctl |= E1000_RCTL_MPE; ++ } else { ++ rctl &= ~E1000_RCTL_MPE; ++ } ++ } ++ ++ uc_ptr = NULL; ++ if (netdev->uc_count > rar_entries - 1) { ++ rctl |= E1000_RCTL_UPE; ++ } else if (!(netdev->flags & IFF_PROMISC)) { ++ rctl &= ~E1000_RCTL_UPE; ++ uc_ptr = netdev->uc_list; + } + +- E1000_WRITE_REG(hw, RCTL, rctl); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + + /* 82542 2.0 needs to be in reset to write receive address registers */ + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_enter_82542_rst(adapter); +- } +- /* load the first 14 multicast address into the exact filters 1-14 ++ ++ /* load the first 14 addresses into the exact filters 1-14. Unicast ++ * addresses take precedence to avoid disabling unicast filtering ++ * when possible. ++ * + * RAR 0 is used for the station MAC adddress + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ + mc_ptr = netdev->mc_list; + +- for (i = 0x1; i < rar_entries; i++) { +- if (mc_ptr) { +- iegbe_rar_set(hw, mc_ptr->dmi_addr, i); ++ for (i = 1; i < rar_entries; i++) { ++ if (uc_ptr) { ++ iegbe_rar_set(hw, uc_ptr->da_addr, i); ++ uc_ptr = uc_ptr->next; ++ } else if (mc_ptr) { ++ iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +- E1000_WRITE_REG_ARRAY(hw, RA, i << 0x1, 0); +- E1000_WRITE_REG_ARRAY(hw, RA, (i << 0x1) + 0x1, 0); ++ E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } + } ++ WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + +- for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++) ++ for (i = 0; i < mta_reg_count; i++) { + E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ } + + /* load any remaining addresses into the hash table */ + + for (; mc_ptr; mc_ptr = mc_ptr->next) { +- hash_value = iegbe_hash_mc_addr(hw, mc_ptr->dmi_addr); ++ hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr); + iegbe_mta_set(hw, hash_value); + } + +- if (hw->mac_type == iegbe_82542_rev2_0) { ++ if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_leave_82542_rst(adapter); + } +-} + + /* Need to wait a few seconds after link up to get diagnostic information from + * the phy */ + +-static void +-iegbe_update_phy_info(unsigned long data) ++static void iegbe_update_phy_info(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- iegbe_phy_get_info(&adapter->hw, &adapter->phy_info); ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ iegbe_phy_get_info(hw, &adapter->phy_info); + } + + /** +@@ -2492,54 +2278,54 @@ iegbe_update_phy_info(unsigned long data + * @data: pointer to adapter cast into an unsigned long + **/ + +-static void +-iegbe_82547_tx_fifo_stall(unsigned long data) ++static void iegbe_82547_tx_fifo_stall(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- uint32_t tctl; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct net_device *netdev = adapter->netdev; ++ u32 tctl; + +- if(atomic_read(&adapter->tx_fifo_stall)) { +- if((E1000_READ_REG(&adapter->hw, TDT) == +- E1000_READ_REG(&adapter->hw, TDH)) && +- (E1000_READ_REG(&adapter->hw, TDFT) == +- E1000_READ_REG(&adapter->hw, TDFH)) && +- (E1000_READ_REG(&adapter->hw, TDFTS) == +- E1000_READ_REG(&adapter->hw, TDFHS))) { +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- E1000_WRITE_REG(&adapter->hw, TCTL, +- tctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, TDFT, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFH, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFTS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TDFHS, +- adapter->tx_head_addr); +- E1000_WRITE_REG(&adapter->hw, TCTL, tctl); +- E1000_WRITE_FLUSH(&adapter->hw); +- +- adapter->tx_fifo_head = 0; +- atomic_set(&adapter->tx_fifo_stall, 0); +- netif_wake_queue(netdev); +- } else { ++ if(atomic_read(&adapter->tx_fifo_stall)) { ++ if((E1000_READ_REG(&adapter->hw, TDT) == ++ E1000_READ_REG(&adapter->hw, TDH)) && ++ (E1000_READ_REG(&adapter->hw, TDFT) == ++ E1000_READ_REG(&adapter->hw, TDFH)) && ++ (E1000_READ_REG(&adapter->hw, TDFTS) == ++ E1000_READ_REG(&adapter->hw, TDFHS))) { ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ E1000_WRITE_REG(&adapter->hw, TCTL, ++ tctl & ~E1000_TCTL_EN); ++ E1000_WRITE_REG(&adapter->hw, TDFT, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFH, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFTS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TDFHS, ++ adapter->tx_head_addr); ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ E1000_WRITE_FLUSH(&adapter->hw); ++ ++ adapter->tx_fifo_head = 0x0; ++ atomic_set(&adapter->tx_fifo_stall, 0x0); ++ netif_wake_queue(netdev); ++ } else { + mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 0x1); +- } +- } ++ } ++ } + } + ++ + /** + * iegbe_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +-static void +-iegbe_watchdog(unsigned long data) ++static void iegbe_watchdog(unsigned long data) + { +- struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_ring *txdr = &adapter->tx_ring[0]; +- uint32_t link; ++ struct iegbe_adapter *adapter = (struct iegbe_adapter *) data; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_ring *txdr = adapter->tx_ring; ++ u32 link, tctl; + + /* + * Test the PHY for link status on icp_xxxx MACs. +@@ -2547,123 +2333,305 @@ iegbe_watchdog(unsigned long data) + * in the adapter->hw structure, then set hw->get_link_status = 1 + */ + if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- int isUp = 0; ++ int isUp = 0x0; + int32_t ret_val; + + ret_val = iegbe_oem_phy_is_link_up(&adapter->hw, &isUp); + if(ret_val != E1000_SUCCESS) { +- isUp = 0; +- } ++ isUp = 0x0; ++ } + if(isUp != adapter->hw.icp_xxxx_is_link_up) { + adapter->hw.get_link_status = 0x1; + } + } + +- iegbe_check_for_link(&adapter->hw); +- if (adapter->hw.mac_type == iegbe_82573) { +- iegbe_enable_tx_pkt_filtering(&adapter->hw); ++ iegbe_check_for_link(&adapter->hw); ++ if (adapter->hw.mac_type == iegbe_82573) { ++ iegbe_enable_tx_pkt_filtering(&adapter->hw); + #ifdef NETIF_F_HW_VLAN_TX + if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) { +- iegbe_update_mng_vlan(adapter); ++ iegbe_update_mng_vlan(adapter); + } + #endif +- } ++ } + +- if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && +- !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { +- link = !adapter->hw.serdes_link_down; +- } else { ++ if ((adapter->hw.media_type == iegbe_media_type_internal_serdes) && ++ !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE)) { ++ link = !adapter->hw.serdes_link_down; ++ } else { + +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; +- } else { +- int isUp = 0; ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } +- link = isUp; +- } +- } ++ link = isUp; ++ } ++ } + +- if (link) { +- if (!netif_carrier_ok(netdev)) { +- iegbe_get_speed_and_duplex(&adapter->hw, +- &adapter->link_speed, +- &adapter->link_duplex); +- +- DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n", +- adapter->link_speed, +- adapter->link_duplex == FULL_DUPLEX ? +- "Full Duplex" : "Half Duplex"); ++ if (link) { ++ if (!netif_carrier_ok(netdev)) { ++ u32 ctrl; ++ bool txb2b = true; ++ iegbe_get_speed_and_duplex(hw, ++ &adapter->link_speed, ++ &adapter->link_duplex); + +- netif_carrier_on(netdev); +- netif_wake_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, " ++ "Flow Control: %s\n", ++ adapter->link_speed, ++ adapter->link_duplex == FULL_DUPLEX ? ++ "Full Duplex" : "Half Duplex", ++ ((ctrl & E1000_CTRL_TFCE) && (ctrl & ++ E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & ++ E1000_CTRL_RFCE) ? "RX" : ((ctrl & ++ E1000_CTRL_TFCE) ? "TX" : "None" ))); ++ ++ /* tweak tx_queue_len according to speed/duplex ++ * and adjust the timeout factor */ ++ netdev->tx_queue_len = adapter->tx_queue_len; ++ adapter->tx_timeout_factor = 1; ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ txb2b = false; ++ netdev->tx_queue_len = 10; ++ adapter->tx_timeout_factor = 8; ++ break; ++ case SPEED_100: ++ txb2b = false; ++ netdev->tx_queue_len = 100; ++ break; ++ } ++ if ((hw->mac_type == iegbe_82571 || ++ hw->mac_type == iegbe_82572) && ++ !txb2b) { ++ u32 tarc0; ++ tarc0 = E1000_READ_REG(&adapter->hw, TARC0); ++ tarc0 &= ~(1 << 21); ++ E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); ++ } ++ /* disable TSO for pcie and 10/100 speeds, to avoid ++ * some hardware issues */ ++ if (!adapter->tso_force && ++ hw->bus_type == iegbe_bus_type_pci_express){ ++ switch (adapter->link_speed) { ++ case SPEED_10: ++ case SPEED_100: ++ DPRINTK(PROBE,INFO, ++ "10/100 speed: disabling TSO\n"); ++ netdev->features &= ~NETIF_F_TSO; ++ netdev->features &= ~NETIF_F_TSO6; ++ break; ++ case SPEED_1000: ++ netdev->features |= NETIF_F_TSO; ++ netdev->features |= NETIF_F_TSO6; ++ break; ++ default: ++ break; ++ } ++ } ++ tctl = E1000_READ_REG(&adapter->hw, TCTL); ++ tctl |= E1000_TCTL_EN; ++ E1000_WRITE_REG(&adapter->hw, TCTL, tctl); ++ netif_carrier_on(netdev); ++ netif_wake_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); + adapter->smartspeed = 0; ++ } else { ++ if (hw->rx_needs_kicking) { ++ u32 rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl | E1000_RCTL_EN); ++ } + } +- } else { +- if (netif_carrier_ok(netdev)) { ++ } else { ++ if (netif_carrier_ok(netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = 0; +- DPRINTK(LINK, INFO, "NIC Link is Down\n"); +- netif_carrier_off(netdev); +- netif_stop_queue(netdev); +- mod_timer(&adapter->phy_info_timer, jiffies + 0x2 * HZ); +- } ++ DPRINTK(LINK, INFO, "NIC Link is Down\n"); ++ netif_carrier_off(netdev); ++ netif_stop_queue(netdev); ++ mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); ++ } + +- iegbe_smartspeed(adapter); +- } ++ iegbe_smartspeed(adapter); ++ } ++ ++ iegbe_update_stats(adapter); ++ ++ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; ++ adapter->tpt_old = adapter->stats.tpt; ++ hw->collision_delta = adapter->stats.colc - adapter->colc_old; ++ adapter->colc_old = adapter->stats.colc; ++ ++ adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; ++ adapter->gorcl_old = adapter->stats.gorcl; ++ adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; ++ adapter->gotcl_old = adapter->stats.gotcl; ++ ++ iegbe_update_adaptive(hw); ++ ++ if (!netif_carrier_ok(netdev)) { ++ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { ++ /* We've lost link, so the controller stops DMA, ++ * but we've got queued Tx work that's never going ++ * to get done, so reset controller to flush Tx. ++ * (Do the reset outside of interrupt context). */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); ++ } ++ } ++ ++ /* Cause software interrupt to ensure rx ring is cleaned */ ++ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++ ++ /* Force detection of hung controller every watchdog period */ ++ adapter->detect_tx_hung = TRUE; ++ ++ /* With 82571 controllers, LAA may be overwritten due to controller ++ * reset from the other port. Set the appropriate LAA in RAR[0] */ ++ if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { ++ iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0x0); ++ } ++ /* Reset the timer */ ++ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); ++} ++ ++enum latency_range { ++ lowest_latency = 0, ++ low_latency = 1, ++ bulk_latency = 2, ++ latency_invalid = 255 ++}; + +- iegbe_update_stats(adapter); ++/** ++ * iegbe_update_itr - update the dynamic ITR value based on statistics ++ * Stores a new ITR value based on packets and byte ++ * counts during the last interrupt. The advantage of per interrupt ++ * computation is faster updates and more accurate ITR for the current ++ * traffic pattern. Constants in this function were computed ++ * based on theoretical maximum wire speed and thresholds were set based ++ * on testing data as well as attempting to minimize response time ++ * while increasing bulk throughput. ++ * this functionality is controlled by the InterruptThrottleRate module ++ * parameter (see iegbe_param.c) ++ * @adapter: pointer to adapter ++ * @itr_setting: current adapter->itr ++ * @packets: the number of packets during this measurement interval ++ * @bytes: the number of bytes during this measurement interval ++ **/ ++static unsigned int iegbe_update_itr(struct iegbe_adapter *adapter, ++ u16 itr_setting, int packets, int bytes) ++{ ++ unsigned int retval = itr_setting; ++ struct iegbe_hw *hw = &adapter->hw; + +- adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; +- adapter->tpt_old = adapter->stats.tpt; +- adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old; +- adapter->colc_old = adapter->stats.colc; +- +- adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; +- adapter->gorcl_old = adapter->stats.gorcl; +- adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; +- adapter->gotcl_old = adapter->stats.gotcl; +- +- iegbe_update_adaptive(&adapter->hw); +- +- if (adapter->num_queues == 0x1 && !netif_carrier_ok(netdev)) { +- if (E1000_DESC_UNUSED(txdr) + 0x1 < txdr->count) { +- /* We've lost link, so the controller stops DMA, +- * but we've got queued Tx work that's never going +- * to get done, so reset controller to flush Tx. +- * (Do the reset outside of interrupt context). */ +- schedule_work(&adapter->tx_timeout_task); ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ goto update_itr_done; ++ ++ if (packets == 0) ++ goto update_itr_done; ++ ++ switch (itr_setting) { ++ case lowest_latency: ++ /* jumbo frames get bulk treatment*/ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 5) && (bytes > 512)) ++ retval = low_latency; ++ break; ++ case low_latency: /* 50 usec aka 20000 ints/s */ ++ if (bytes > 10000) { ++ /* jumbo frames need bulk latency setting */ ++ if (bytes/packets > 8000) ++ retval = bulk_latency; ++ else if ((packets < 10) || ((bytes/packets) > 1200)) ++ retval = bulk_latency; ++ else if ((packets > 35)) ++ retval = lowest_latency; ++ } else if (bytes/packets > 2000) ++ retval = bulk_latency; ++ else if (packets <= 2 && bytes < 512) ++ retval = lowest_latency; ++ break; ++ case bulk_latency: /* 250 usec aka 4000 ints/s */ ++ if (bytes > 25000) { ++ if (packets > 35) ++ retval = low_latency; ++ } else if (bytes < 6000) { ++ retval = low_latency; + } ++ break; + } + +- /* Dynamic mode for Interrupt Throttle Rate (ITR) */ +- if (adapter->hw.mac_type >= iegbe_82540 && adapter->itr == 0x1) { +- /* Symmetric Tx/Rx gets a reduced ITR=2000; Total +- * asymmetrical Tx or Rx gets ITR=8000; everyone +- * else is between 2000-8000. */ +- uint32_t goc = (adapter->gotcl + adapter->gorcl) / 0x2710; +- uint32_t dif = (adapter->gotcl > adapter->gorcl ? +- adapter->gotcl - adapter->gorcl : +- adapter->gorcl - adapter->gotcl) / 0x2710; +- uint32_t itr = goc > 0 ? (dif * 0x1770 / goc + 0x7d0) : 0x1f40; +- E1000_WRITE_REG(&adapter->hw, ITR, 0x3b9aca00 / (itr * 0x100)); +- } ++update_itr_done: ++ return retval; ++} + +- /* Cause software interrupt to ensure rx ring is cleaned */ +- E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); ++static void iegbe_set_itr(struct iegbe_adapter *adapter) ++{ ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 current_itr; ++ u32 new_itr = adapter->itr; + +- /* Force detection of hung controller every watchdog period */ +- adapter->detect_tx_hung = TRUE; ++ if (unlikely(hw->mac_type < iegbe_82540)) ++ return; + +- /* With 82571 controllers, LAA may be overwritten due to controller +- * reset from the other port. Set the appropriate LAA in RAR[0] */ +- if (adapter->hw.mac_type == iegbe_82571 && adapter->hw.laa_is_present) { +- iegbe_rar_set(&adapter->hw, adapter->hw.mac_addr, 0); +- } +- /* Reset the timer */ +- mod_timer(&adapter->watchdog_timer, jiffies + 0x2 * HZ); ++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ ++ if (unlikely(adapter->link_speed != SPEED_1000)) { ++ current_itr = 0; ++ new_itr = 4000; ++ goto set_itr_now; ++ } ++ ++ adapter->tx_itr = iegbe_update_itr(adapter, ++ adapter->tx_itr, ++ adapter->total_tx_packets, ++ adapter->total_tx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) ++ adapter->tx_itr = low_latency; ++ ++ adapter->rx_itr = iegbe_update_itr(adapter, ++ adapter->rx_itr, ++ adapter->total_rx_packets, ++ adapter->total_rx_bytes); ++ /* conservative mode (itr 3) eliminates the lowest_latency setting */ ++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) ++ adapter->rx_itr = low_latency; ++ ++ current_itr = max(adapter->rx_itr, adapter->tx_itr); ++ ++ switch (current_itr) { ++ /* counts and packets in update_itr are dependent on these numbers */ ++ case lowest_latency: ++ new_itr = 70000; ++ break; ++ case low_latency: ++ new_itr = 20000; /* aka hwitr = ~200 */ ++ break; ++ case bulk_latency: ++ new_itr = 4000; ++ break; ++ default: ++ break; ++ } ++ ++set_itr_now: ++ if (new_itr != adapter->itr) { ++ /* this attempts to bias the interrupt rate towards Bulk ++ * by adding intermediate steps when interrupt rate is ++ * increasing */ ++ new_itr = new_itr > adapter->itr ? ++ min(adapter->itr + (new_itr >> 2), new_itr) : ++ new_itr; ++ adapter->itr = new_itr; ++ E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (new_itr * 256)); ++ } ++ ++ return; + } + + #define E1000_TX_FLAGS_CSUM 0x00000001 +@@ -2673,55 +2641,48 @@ iegbe_watchdog(unsigned long data) + #define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 + #define E1000_TX_FLAGS_VLAN_SHIFT 16 + +-static inline int +-iegbe_tso(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static int iegbe_tso(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { +-#ifdef NETIF_F_TSO + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint32_t cmd_length = 0; +- uint16_t ipcse = 0, tucse, mss; +- uint8_t ipcss, ipcso, tucss, tucso, hdr_len; ++ u32 cmd_length = 0; ++ u16 ipcse = 0, tucse, mss; ++ u8 ipcss, ipcso, tucss, tucso, hdr_len; + int err; + + if (skb_is_gso(skb)) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +- if (err) { ++ if (err) + return err; + } +- } + +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + mss = skb_shinfo(skb)->gso_size; + if (skb->protocol == htons(ETH_P_IP)) { +- skb->nh.iph->tot_len = 0; +- skb->nh.iph->check = 0; +- skb->h.th->check = +- ~csum_tcpudp_magic(skb->nh.iph->saddr, +- skb->nh.iph->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ struct iphdr *iph = ip_hdr(skb); ++ iph->tot_len = 0; ++ iph->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, ++ iph->daddr, 0, ++ IPPROTO_TCP, ++ 0); + cmd_length = E1000_TXD_CMD_IP; +- ipcse = skb->h.raw - skb->data - 0x1; +-#ifdef NETIF_F_TSO_IPV6 +- } else if (skb->protocol == ntohs(ETH_P_IPV6)) { +- skb->nh.ipv6h->payload_len = 0; +- skb->h.th->check = +- ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, +- &skb->nh.ipv6h->daddr, +- 0, +- IPPROTO_TCP, +- 0); ++ ipcse = skb_transport_offset(skb) - 1; ++ } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ++ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); + ipcse = 0; +-#endif + } +- ipcss = skb->nh.raw - skb->data; +- ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; +- tucss = skb->h.raw - skb->data; +- tucso = (void *)&(skb->h.th->check) - (void *)skb->data; ++ ipcss = skb_network_offset(skb); ++ ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; ++ tucss = skb_transport_offset(skb); ++ tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; + tucse = 0; + + cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | +@@ -2729,6 +2690,7 @@ iegbe_tso(struct iegbe_adapter *adapter, + + i = tx_ring->next_to_use; + context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; + + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; +@@ -2740,205 +2702,218 @@ iegbe_tso(struct iegbe_adapter *adapter, + context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; + context_desc->cmd_and_length = cpu_to_le32(cmd_length); + +- if (++i == tx_ring->count) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (++i == tx_ring->count) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } +-#endif +- +- return FALSE; ++ return false; + } + +-static inline boolean_t +-iegbe_tx_csum(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb) ++static bool iegbe_tx_csum(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, struct sk_buff *skb) + { + struct iegbe_context_desc *context_desc; ++ struct iegbe_buffer *buffer_info; + unsigned int i; +- uint8_t css; ++ u8 css; + +- if (likely(skb->ip_summed == CHECKSUM_HW)) { +- css = skb->h.raw - skb->data; ++ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ css = skb_transport_offset(skb); + +- i = tx_ring->next_to_use; +- context_desc = E1000_CONTEXT_DESC(*tx_ring, i); ++ i = tx_ring->next_to_use; ++ buffer_info = &tx_ring->buffer_info[i]; ++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i); + ++ context_desc->lower_setup.ip_config = 0; + context_desc->upper_setup.tcp_fields.tucss = css; +- context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; ++ context_desc->upper_setup.tcp_fields.tucso = ++ css + skb->csum_offset; + context_desc->upper_setup.tcp_fields.tucse = 0; + context_desc->tcp_seg_setup.data = 0; + context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); + +- if (unlikely(++i == tx_ring->count)) { i = 0; } ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ if (unlikely(++i == tx_ring->count)) i = 0; + tx_ring->next_to_use = i; + +- return TRUE; ++ return true; + } + +- return FALSE; ++ return false; + } + +-#define E1000_MAX_TXD_PWR 12 +-#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR) ++#define E1000_MAX_TXD_PWR 12 ++#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR) + +-static inline int +-iegbe_tx_map(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- struct sk_buff *skb, unsigned int first, unsigned int max_per_txd, +- unsigned int nr_frags, unsigned int mss) ++static int iegbe_tx_map(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, ++ struct sk_buff *skb, unsigned int first, ++ unsigned int max_per_txd, unsigned int nr_frags, ++ unsigned int mss) + { +- struct iegbe_buffer *buffer_info; +- unsigned int len = skb->len; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct iegbe_buffer *buffer_info; ++ unsigned int len = skb->len; + unsigned int offset = 0, size, count = 0, i; +-#ifdef MAX_SKB_FRAGS +- unsigned int f; +- len -= skb->data_len; +-#endif ++ unsigned int f; ++ len -= skb->data_len; + +- i = tx_ring->next_to_use; ++ i = tx_ring->next_to_use; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for Controller erratum -- ++ * descriptor for non-tso packet in a linear SKB that follows a ++ * tso gets written back prematurely before the data is fully ++ * DMA'd to the controller */ ++ if (!skb->data_len && tx_ring->last_tx_tso && ++ !skb_is_gso(skb)) { ++ tx_ring->last_tx_tso = 0; ++ size -= 4; ++ } + +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO + /* Workaround for premature desc write-backs + * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && !nr_frags && size == len && size > 0x8)) { +- size -= 0x4; ++ if (unlikely(mss && !nr_frags && size == len && size > 8)) ++ size -= 4; ++ /* work-around for errata 10 and it applies ++ * to all controllers in PCI-X mode ++ * The fix is to make sure that the first descriptor of a ++ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes ++ */ ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (size > 2015) && count == 0)) ++ size = 2015; ++ ++ /* Workaround for potential 82544 hang in PCI-X. Avoid ++ * terminating buffers within evenly-aligned dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(skb->data + offset + size - 1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_single(adapter->pdev, ++ skb->data + offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ for (f = 0; f < nr_frags; f++) { ++ struct skb_frag_struct *frag; ++ ++ frag = &skb_shinfo(skb)->frags[f]; ++ len = frag->size; ++ offset = frag->page_offset; ++ ++ while(len) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ size = min(len, max_per_txd); ++ /* Workaround for premature desc write-backs ++ * in TSO mode. Append 4-byte sentinel desc */ ++ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) ++ size -= 4; ++ /* Workaround for potential 82544 hang in PCI-X. ++ * Avoid terminating buffers within evenly-aligned ++ * dwords. */ ++ if(unlikely(adapter->pcix_82544 && ++ !((unsigned long)(frag->page+offset+size-1) & 4) && ++ size > 4)) ++ size -= 4; ++ ++ buffer_info->length = size; ++ buffer_info->dma = ++ pci_map_page(adapter->pdev, ++ frag->page, ++ offset, ++ size, ++ PCI_DMA_TODEVICE); ++ buffer_info->time_stamp = jiffies; ++ buffer_info->next_to_watch = i; ++ ++ len -= size; ++ offset += size; ++ count++; ++ if (unlikely(++i == tx_ring->count)) i = 0; + } +-#endif +- /* work-around for errata 10 and it applies +- * to all controllers in PCI-X mode +- * The fix is to make sure that the first descriptor of a +- * packet is smaller than 2048 - 16 - 16 (or 2016) bytes +- */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (size > 0x7df) && count == 0)) { +- size = 0x7df; +- } +- /* Workaround for potential 82544 hang in PCI-X. Avoid +- * terminating buffers within evenly-aligned dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(skb->data + offset + size - 0x8) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_single(adapter->pdev, +- skb->data + offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +-#ifdef MAX_SKB_FRAGS +- for(f = 0; f < nr_frags; f++) { +- struct skb_frag_struct *frag; +- +- frag = &skb_shinfo(skb)->frags[f]; +- len = frag->size; +- offset = frag->page_offset; +- +- while(len) { +- buffer_info = &tx_ring->buffer_info[i]; +- size = min(len, max_per_txd); +-#ifdef NETIF_F_TSO +- /* Workaround for premature desc write-backs +- * in TSO mode. Append 4-byte sentinel desc */ +- if(unlikely(mss && f == (nr_frags-0x1) && +- size == len && size > 0x8)) { +- size -= 0x4; +- } +-#endif +- /* Workaround for potential 82544 hang in PCI-X. +- * Avoid terminating buffers within evenly-aligned +- * dwords. */ +- if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(frag->page+offset+size-0x1) & 0x4) && +- size > 0x4)) { +- size -= 0x4; +- } +- buffer_info->length = size; +- buffer_info->dma = +- pci_map_page(adapter->pdev, +- frag->page, +- offset, +- size, +- PCI_DMA_TODEVICE); +- buffer_info->time_stamp = jiffies; +- +- len -= size; +- offset += size; +- count++; +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- } +-#endif ++ } + +- i = (i == 0) ? tx_ring->count - 0x1 : i - 0x1; +- tx_ring->buffer_info[i].skb = skb; +- tx_ring->buffer_info[first].next_to_watch = i; ++ i = (i == 0) ? tx_ring->count - 1 : i - 1; ++ tx_ring->buffer_info[i].skb = skb; ++ tx_ring->buffer_info[first].next_to_watch = i; + +- return count; ++ return count; + } + +-static inline void +-iegbe_tx_queue(struct iegbe_adapter *adapter, struct iegbe_tx_ring *tx_ring, +- int tx_flags, int count) ++static void iegbe_tx_queue(struct iegbe_adapter *adapter, ++ struct iegbe_tx_ring *tx_ring, int tx_flags, ++ int count) + { ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_desc *tx_desc = NULL; + struct iegbe_buffer *buffer_info; +- uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; ++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; + unsigned int i; + +- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | + E1000_TXD_CMD_TSE; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + +- if(likely(tx_flags & E1000_TX_FLAGS_IPV4)) { +- txd_upper |= E1000_TXD_POPTS_IXSM << 0x8; +- } ++ if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) ++ txd_upper |= E1000_TXD_POPTS_IXSM << 8; + } + +- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) { ++ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { + txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; +- txd_upper |= E1000_TXD_POPTS_TXSM << 0x8; +- } +- +- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { +- txd_lower |= E1000_TXD_CMD_VLE; +- txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ txd_upper |= E1000_TXD_POPTS_TXSM << 8; + } + +- i = tx_ring->next_to_use; ++ if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { ++ txd_lower |= E1000_TXD_CMD_VLE; ++ txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); ++ } + +- while(count--) { +- buffer_info = &tx_ring->buffer_info[i]; +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- tx_desc->lower.data = +- cpu_to_le32(txd_lower | buffer_info->length); +- tx_desc->upper.data = cpu_to_le32(txd_upper); +- if(unlikely(++i == tx_ring->count)) { i = 0; } +- } +- if(tx_desc != NULL) { +- tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); +- } +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); ++ i = tx_ring->next_to_use; + +- tx_ring->next_to_use = i; +- writel(i, adapter->hw.hw_addr + tx_ring->tdt); ++ while(count--) { ++ buffer_info = &tx_ring->buffer_info[i]; ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); ++ tx_desc->lower.data = ++ cpu_to_le32(txd_lower | buffer_info->length); ++ tx_desc->upper.data = cpu_to_le32(txd_upper); ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } ++ ++ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ ++ tx_ring->next_to_use = i; ++ writel(i, hw->hw_addr + tx_ring->tdt); ++ /* we need this if more than one processor can write to our tail ++ * at a time, it syncronizes IO on IA64/Altix systems */ ++ mmiowb(); + } + + /** +@@ -2950,113 +2925,132 @@ iegbe_tx_queue(struct iegbe_adapter *ada + * to the beginning of the Tx FIFO. + **/ + +-static inline int +-iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define E1000_FIFO_HDR 0x10 ++#define E1000_82547_PAD_LEN 0x3E0 ++static int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { +- uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; +- uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR; ++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; ++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR; + +- E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); ++ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR); + +- if(adapter->link_duplex != HALF_DUPLEX) { +- goto no_fifo_stall_required; +- } +- if(atomic_read(&adapter->tx_fifo_stall)) { +- return 1; ++ if (adapter->link_duplex != HALF_DUPLEX) ++ goto no_fifo_stall_required; ++ ++ if (atomic_read(&adapter->tx_fifo_stall)) ++ return 1; ++ ++ if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { ++ atomic_set(&adapter->tx_fifo_stall, 1); ++ return 1; + } +- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { +- atomic_set(&adapter->tx_fifo_stall, 0x1); +- return 1; +- } + + no_fifo_stall_required: +- adapter->tx_fifo_head += skb_fifo_len; +- if(adapter->tx_fifo_head >= adapter->tx_fifo_size) { +- adapter->tx_fifo_head -= adapter->tx_fifo_size; +- } ++ adapter->tx_fifo_head += skb_fifo_len; ++ if (adapter->tx_fifo_head >= adapter->tx_fifo_size) ++ adapter->tx_fifo_head -= adapter->tx_fifo_size; + return 0; + } + +-static inline int +-iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, struct sk_buff *skb) ++#define MINIMUM_DHCP_PACKET_SIZE 282 ++static int iegbe_transfer_dhcp_info(struct iegbe_adapter *adapter, ++ struct sk_buff *skb) + { + struct iegbe_hw *hw = &adapter->hw; +- uint16_t length, offset; +-#ifdef NETIF_F_HW_VLAN_TX +- if(vlan_tx_tag_present(skb)) { +- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && +- ( adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) { ++ u16 length, offset; ++ if (vlan_tx_tag_present(skb)) { ++ if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) && ++ ( hw->mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) ) + return 0; + } +- } +-#endif +- if(htons(ETH_P_IP) == skb->protocol) { +- const struct iphdr *ip = skb->nh.iph; +- if(IPPROTO_UDP == ip->protocol) { +- struct udphdr *udp = (struct udphdr *)(skb->h.uh); +- if(ntohs(udp->dest) == 0x43) { /* 0x43 = 67 */ +- offset = (uint8_t *)udp + 0x8 - skb->data; +- length = skb->len - offset; +- +- return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, length); +- } +- } +- } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) { +- struct ethhdr *eth = (struct ethhdr *) skb->data; +- if((htons(ETH_P_IP) == eth->h_proto)) { ++ if (skb->len > MINIMUM_DHCP_PACKET_SIZE) { ++ struct ethhdr *eth = (struct ethhdr *)skb->data; ++ if ((htons(ETH_P_IP) == eth->h_proto)) { + const struct iphdr *ip = +- (struct iphdr *)((uint8_t *)skb->data+0xe); +- if(IPPROTO_UDP == ip->protocol) { ++ (struct iphdr *)((u8 *)skb->data+14); ++ if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = +- (struct udphdr *)((uint8_t *)ip + +- (ip->ihl << 0x2)); +- if(ntohs(udp->dest) == 0x43) { +- offset = (uint8_t *)udp + 0x8 - skb->data; ++ (struct udphdr *)((u8 *)ip + ++ (ip->ihl << 2)); ++ if (ntohs(udp->dest) == 67) { ++ offset = (u8 *)udp + 8 - skb->data; + length = skb->len - offset; + + return iegbe_mng_write_dhcp_info(hw, +- (uint8_t *)udp + 0x8, ++ (u8 *)udp + 8, + length); +- } ++ } + } + } + } + return 0; + } + +-static int +-iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ++static int __iegbe_maybe_stop_tx(struct net_device *netdev, int size) ++{ ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_tx_ring *tx_ring = adapter->tx_ring; ++ ++ netif_stop_queue(netdev); ++ /* Herbert's original patch had: ++ * smp_mb__after_netif_stop_queue(); ++ * but since that doesn't exist yet, just open code it. */ ++ smp_mb(); ++ ++ /* We need to check again in a case another CPU has just ++ * made room available. */ ++ if (likely(E1000_DESC_UNUSED(tx_ring) < size)) ++ return -EBUSY; ++ ++ /* A reprieve! */ ++ netif_start_queue(netdev); ++ ++adapter->restart_queue; ++ return 0; ++} ++ ++static int iegbe_maybe_stop_tx(struct net_device *netdev, ++ struct iegbe_tx_ring *tx_ring, int size) ++{ ++ if (likely(E1000_DESC_UNUSED(tx_ring) >= size)) ++ return 0; ++ return __iegbe_maybe_stop_tx(netdev, size); ++} ++ ++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) ++static int iegbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; + struct iegbe_tx_ring *tx_ring; + unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; + unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; + unsigned int tx_flags = 0; +- unsigned int len = skb->len; ++ unsigned int len = skb->len - skb->data_len; + unsigned long flags = 0; +- unsigned int nr_frags = 0; +- unsigned int mss = 0; ++ unsigned int nr_frags; ++ unsigned int mss; + int count = 0; +- int tso; +-#ifdef MAX_SKB_FRAGS ++ int tso; + unsigned int f; +- len -= skb->data_len; +-#endif + +-#ifdef CONFIG_E1000_MQ +- tx_ring = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id()); +-#else ++ /* This goes back to the question of how to logically map a tx queue ++ * to a flow. Right now, performance is impacted slightly negatively ++ * if using multiple tx queues. If the stack breaks away from a ++ * single qdisc implementation, we can look at this again. */ + tx_ring = adapter->tx_ring; +-#endif + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +-#ifdef NETIF_F_TSO ++ /* 82571 and newer doesn't need the workaround that limited descriptor ++ * length to 4kB */ ++ if (hw->mac_type >= iegbe_82571) ++ max_per_txd = 8192; ++ + mss = skb_shinfo(skb)->gso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before +@@ -3064,164 +3058,150 @@ iegbe_xmit_frame(struct sk_buff *skb, st + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ +- if(mss) { +- max_per_txd = min(mss << 0x2, max_per_txd); +- max_txd_pwr = fls(max_per_txd) - 0x1; ++ if (mss) { ++ u8 hdr_len; ++ max_per_txd = min(mss << 2, max_per_txd); ++ max_txd_pwr = fls(max_per_txd) - 1; ++ ++ /* TSO Workaround for 82571/2/3 Controllers -- if skb->data ++ * points to just header, pull a few bytes of payload from ++ * frags into skb->data */ ++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); ++ if (skb->data_len && hdr_len == len) { ++ switch (hw->mac_type) { ++ case iegbe_82544: ++ /* Make sure we have room to chop off 4 bytes, ++ * and that the end alignment will work out to ++ * this hardware's requirements ++ * NOTE: this is a TSO only workaround ++ * if end byte alignment not correct move us ++ * into the next dword */ ++ break; ++ /* fall through */ ++ case iegbe_82571: ++ case iegbe_82572: ++ case iegbe_82573: ++ break; ++ default: ++ /* do nothing */ ++ break; ++ } ++ } + } + +- if((mss) || (skb->ip_summed == CHECKSUM_HW)) { ++ /* reserve a descriptor for the offload context */ ++ if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) + count++; +- } + count++; +-#else +- if(skb->ip_summed == CHECKSUM_HW) { ++ ++ /* Controller Erratum workaround */ ++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) + count++; +- { +-#endif ++ + count += TXD_USE_COUNT(len, max_txd_pwr); + +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count++; +- } ++ + /* work-around for errata 10 and it applies to all controllers + * in PCI-X mode, so add one more descriptor to the count + */ +- if(unlikely((adapter->hw.bus_type == iegbe_bus_type_pcix) && +- (len > 0x7df))) { ++ if (unlikely((hw->bus_type == iegbe_bus_type_pcix) && ++ (len > 2015))) + count++; +- } +-#ifdef MAX_SKB_FRAGS ++ + nr_frags = skb_shinfo(skb)->nr_frags; +- for(f = 0; f < nr_frags; f++) ++ for (f = 0; f < nr_frags; f++) + count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, + max_txd_pwr); +- if(adapter->pcix_82544) { ++ if (adapter->pcix_82544) + count += nr_frags; +- } +-#ifdef NETIF_F_TSO +- /* TSO Workaround for 82571/2 Controllers -- if skb->data +- * points to just header, pull a few bytes of payload from +- * frags into skb->data */ +- if (skb_is_gso(skb)) { +- uint8_t hdr_len; +- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 0x2)); +- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) && +- (adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572)) { +- unsigned int pull_size; +- pull_size = min((unsigned int)0x4, skb->data_len); +- if (!__pskb_pull_tail(skb, pull_size)) { +- printk(KERN_ERR "__pskb_pull_tail failed.\n"); +- dev_kfree_skb_any(skb); +- return -EFAULT; +- } +- } +- } +-#endif +-#endif + +- if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == iegbe_82573) ) { ++ ++ if (hw->tx_pkt_filtering && ++ (hw->mac_type == iegbe_82573)) + iegbe_transfer_dhcp_info(adapter, skb); +- } +-#ifdef NETIF_F_LLTX +- local_irq_save(flags); +- if (!spin_trylock(&tx_ring->tx_lock)) { ++ ++ if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) + /* Collision - tell upper layer to requeue */ +- local_irq_restore(flags); + return NETDEV_TX_LOCKED; +- } +-#else +- spin_lock_irqsave(&tx_ring->tx_lock, flags); +-#endif + + /* need: count + 2 desc gap to keep tail from touching + * head, otherwise try next time */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < count + 0x2)) { +- netif_stop_queue(netdev); ++ if (unlikely(iegbe_maybe_stop_tx(netdev, tx_ring, count + 2))) { + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + +- if(unlikely(adapter->hw.mac_type == iegbe_82547)) { +- if(unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { ++ if (unlikely(hw->mac_type == iegbe_82547)) { ++ if (unlikely(iegbe_82547_fifo_workaround(adapter, skb))) { + netif_stop_queue(netdev); +- mod_timer(&adapter->tx_fifo_stall_timer, jiffies); ++ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_BUSY; + } + } + +-#ifndef NETIF_F_LLTX +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif +- +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { ++ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { + tx_flags |= E1000_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); + } +-#endif + + first = tx_ring->next_to_use; + + tso = iegbe_tso(adapter, tx_ring, skb); + if (tso < 0) { + dev_kfree_skb_any(skb); +-#ifdef NETIF_F_LLTX + spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif + return NETDEV_TX_OK; + } + +- if (likely(tso)) { ++ if (likely(tso)) { ++ tx_ring->last_tx_tso = 1; + tx_flags |= E1000_TX_FLAGS_TSO; +- } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) { ++ } else if (likely(iegbe_tx_csum(adapter, tx_ring, skb))) + tx_flags |= E1000_TX_FLAGS_CSUM; +- } ++ + /* Old method was to assume IPv4 packet by default if TSO was enabled. + * 82571 hardware supports TSO capabilities for IPv6 as well... + * no longer assume, we must. */ +- if (likely(skb->protocol == ntohs(ETH_P_IP))) { ++ if (likely(skb->protocol == htons(ETH_P_IP))) + tx_flags |= E1000_TX_FLAGS_IPV4; +- } ++ + iegbe_tx_queue(adapter, tx_ring, tx_flags, + iegbe_tx_map(adapter, tx_ring, skb, first, + max_per_txd, nr_frags, mss)); + + netdev->trans_start = jiffies; + +-#ifdef NETIF_F_LLTX + /* Make sure there is space in the ring for the next send. */ +- if (unlikely(E1000_DESC_UNUSED(tx_ring) < MAX_SKB_FRAGS + 0x2)) { +- netif_stop_queue(netdev); +- } +- spin_unlock_irqrestore(&tx_ring->tx_lock, flags); +-#endif ++ iegbe_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); + ++ spin_unlock_irqrestore(&tx_ring->tx_lock, flags); + return NETDEV_TX_OK; + } + ++ + /** + * iegbe_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ + +-static void +-iegbe_tx_timeout(struct net_device *netdev) ++static void iegbe_tx_timeout(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- /* Do the reset outside of interrupt context */ +- schedule_work(&adapter->tx_timeout_task); ++ /* Do the reset outside of interrupt context */ ++ adapter->tx_timeout_count++; ++ schedule_work(&adapter->reset_task); + } + +-static void +-iegbe_tx_timeout_task(struct net_device *netdev) ++static void iegbe_reset_task(struct work_struct *work) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = ++ container_of(work, struct iegbe_adapter, reset_task); + +- iegbe_down(adapter); +- iegbe_up(adapter); ++ iegbe_reinit_locked(adapter); + } + + /** +@@ -3232,13 +3212,12 @@ iegbe_tx_timeout_task(struct net_device + * The statistics are actually updated from the timer callback. + **/ + +-static struct net_device_stats * +-iegbe_get_stats(struct net_device *netdev) ++static struct net_device_stats *iegbe_get_stats(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); + +- iegbe_update_stats(adapter); +- return &adapter->net_stats; ++ /* only return the current stats */ ++ return &adapter->net_stats; + } + + /** +@@ -3249,67 +3228,55 @@ iegbe_get_stats(struct net_device *netde + * Returns 0 on success, negative on failure + **/ + +-static int +-iegbe_change_mtu(struct net_device *netdev, int new_mtu) ++static int iegbe_change_mtu(struct net_device *netdev, int new_mtu) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + +- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || +- (max_frame > MAX_JUMBO_FRAME_SIZE)) { +- DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); +- return -EINVAL; +- } ++ if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || ++ (max_frame > MAX_JUMBO_FRAME_SIZE)) { ++ DPRINTK(PROBE, ERR, "Invalid MTU setting\n"); ++ return -EINVAL; ++ } + ++ /* Adapter-specific max frame size limits. */ ++ switch (hw->mac_type) { ++ case iegbe_undefined ... iegbe_82542_rev2_1: ++ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n"); ++ return -EINVAL; ++ } ++ break; ++ case iegbe_82571: ++ case iegbe_82572: + #define MAX_STD_JUMBO_FRAME_SIZE 9234 +- /* might want this to be bigger enum check... */ +- /* 82571 controllers limit jumbo frame size to 10500 bytes */ +- if ((adapter->hw.mac_type == iegbe_82571 || +- adapter->hw.mac_type == iegbe_82572) && +- max_frame > MAX_STD_JUMBO_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported " +- "on 82571 and 82572 controllers.\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type == iegbe_82573 && +- max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82573\n"); +- return -EINVAL; +- } +- +- if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- adapter->rx_buffer_len = max_frame; +- E1000_ROUNDUP(adapter->rx_buffer_len, 0x1024); +- } else { +- if(unlikely((adapter->hw.mac_type < iegbe_82543) && +- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { +- DPRINTK(PROBE, ERR, "Jumbo Frames not supported " +- "on 82542\n"); +- return -EINVAL; +- +- } else { +- if(max_frame <= E1000_RXBUFFER_2048) { +- adapter->rx_buffer_len = E1000_RXBUFFER_2048; +- } else if(max_frame <= E1000_RXBUFFER_4096) { +- adapter->rx_buffer_len = E1000_RXBUFFER_4096; +- } else if(max_frame <= E1000_RXBUFFER_8192) { +- adapter->rx_buffer_len = E1000_RXBUFFER_8192; +- } else if(max_frame <= E1000_RXBUFFER_16384) { +- adapter->rx_buffer_len = E1000_RXBUFFER_16384; +- } ++ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { ++ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n"); ++ return -EINVAL; + } ++ break; ++ default: ++ break; + } ++ if (max_frame <= E1000_RXBUFFER_256) ++ adapter->rx_buffer_len = E1000_RXBUFFER_256; ++ else if (max_frame <= E1000_RXBUFFER_2048) ++ adapter->rx_buffer_len = E1000_RXBUFFER_2048; ++ else if (max_frame <= E1000_RXBUFFER_4096) ++ adapter->rx_buffer_len = E1000_RXBUFFER_4096; ++ else if (max_frame <= E1000_RXBUFFER_8192) ++ adapter->rx_buffer_len = E1000_RXBUFFER_8192; ++ else if (max_frame <= E1000_RXBUFFER_16384) ++ adapter->rx_buffer_len = E1000_RXBUFFER_16384; + +- netdev->mtu = new_mtu; ++ /* adjust allocation if LPE protects us, and we aren't using SBP */ + +- if(netif_running(netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); +- } ++ netdev->mtu = new_mtu; ++ hw->max_frame_size = max_frame; + +- adapter->hw.max_frame_size = max_frame; ++ if (netif_running(netdev)) ++ iegbe_reinit_locked(adapter); + + return 0; + } +@@ -3319,224 +3286,189 @@ iegbe_change_mtu(struct net_device *netd + * @adapter: board private structure + **/ + +-void +-iegbe_update_stats(struct iegbe_adapter *adapter) ++void iegbe_update_stats(struct iegbe_adapter *adapter) + { +- struct iegbe_hw *hw = &adapter->hw; +- unsigned long flags = 0; +- uint16_t phy_tmp; ++ struct iegbe_hw *hw = &adapter->hw; ++ unsigned long flags = 0x0; ++ uint16_t phy_tmp; + + #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF + +- spin_lock_irqsave(&adapter->stats_lock, flags); ++ spin_lock_irqsave(&adapter->stats_lock, flags); + +- /* these counters are modified from iegbe_adjust_tbi_stats, +- * called from the interrupt context, so they must only +- * be written while holding adapter->stats_lock +- */ ++ /* these counters are modified from iegbe_adjust_tbi_stats, ++ * called from the interrupt context, so they must only ++ * be written while holding adapter->stats_lock ++ */ + +- adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); +- adapter->stats.gprc += E1000_READ_REG(hw, GPRC); +- adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); +- adapter->stats.gorch += E1000_READ_REG(hw, GORCH); +- adapter->stats.bprc += E1000_READ_REG(hw, BPRC); +- adapter->stats.mprc += E1000_READ_REG(hw, MPRC); +- adapter->stats.roc += E1000_READ_REG(hw, ROC); +- adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); +- adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); +- adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); +- adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); +- adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); +- adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); +- +- adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); +- adapter->stats.mpc += E1000_READ_REG(hw, MPC); +- adapter->stats.scc += E1000_READ_REG(hw, SCC); +- adapter->stats.ecol += E1000_READ_REG(hw, ECOL); +- adapter->stats.mcc += E1000_READ_REG(hw, MCC); +- adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); +- adapter->stats.dc += E1000_READ_REG(hw, DC); +- adapter->stats.sec += E1000_READ_REG(hw, SEC); +- adapter->stats.rlec += E1000_READ_REG(hw, RLEC); +- adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); +- adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); +- adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); +- adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); +- adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); +- adapter->stats.gptc += E1000_READ_REG(hw, GPTC); +- adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); +- adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); +- adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); +- adapter->stats.ruc += E1000_READ_REG(hw, RUC); +- adapter->stats.rfc += E1000_READ_REG(hw, RFC); +- adapter->stats.rjc += E1000_READ_REG(hw, RJC); +- adapter->stats.torl += E1000_READ_REG(hw, TORL); +- adapter->stats.torh += E1000_READ_REG(hw, TORH); +- adapter->stats.totl += E1000_READ_REG(hw, TOTL); +- adapter->stats.toth += E1000_READ_REG(hw, TOTH); +- adapter->stats.tpr += E1000_READ_REG(hw, TPR); +- adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); +- adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); +- adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); +- adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); +- adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); +- adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); +- adapter->stats.mptc += E1000_READ_REG(hw, MPTC); +- adapter->stats.bptc += E1000_READ_REG(hw, BPTC); +- +- /* used for adaptive IFS */ +- +- hw->tx_packet_delta = E1000_READ_REG(hw, TPT); +- adapter->stats.tpt += hw->tx_packet_delta; +- hw->collision_delta = E1000_READ_REG(hw, COLC); +- adapter->stats.colc += hw->collision_delta; +- +- if(hw->mac_type >= iegbe_82543) { +- adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); +- adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); +- adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); +- adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); +- adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); +- adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); +- } +- if(hw->mac_type > iegbe_82547_rev_2) { +- adapter->stats.iac += E1000_READ_REG(hw, IAC); +- adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); +- adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); +- adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); +- adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); +- adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); +- adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); +- adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); +- adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); +- } +- +- /* Fill out the OS statistics structure */ +- +- adapter->net_stats.rx_packets = adapter->stats.gprc; +- adapter->net_stats.tx_packets = adapter->stats.gptc; +- adapter->net_stats.rx_bytes = adapter->stats.gorcl; +- adapter->net_stats.tx_bytes = adapter->stats.gotcl; +- adapter->net_stats.multicast = adapter->stats.mprc; +- adapter->net_stats.collisions = adapter->stats.colc; +- +- /* Rx Errors */ +- +- adapter->net_stats.rx_errors = adapter->stats.rxerrc + +- adapter->stats.crcerrs + adapter->stats.algnerrc + +- adapter->stats.rlec + adapter->stats.mpc + +- adapter->stats.cexterr; +- adapter->net_stats.rx_dropped = adapter->stats.mpc; +- adapter->net_stats.rx_length_errors = adapter->stats.rlec; +- adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; +- adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; +- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; +- adapter->net_stats.rx_missed_errors = adapter->stats.mpc; +- +- /* Tx Errors */ +- +- adapter->net_stats.tx_errors = adapter->stats.ecol + +- adapter->stats.latecol; +- adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; +- adapter->net_stats.tx_window_errors = adapter->stats.latecol; +- adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; ++ adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); ++ adapter->stats.gprc += E1000_READ_REG(hw, GPRC); ++ adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); ++ adapter->stats.gorch += E1000_READ_REG(hw, GORCH); ++ adapter->stats.bprc += E1000_READ_REG(hw, BPRC); ++ adapter->stats.mprc += E1000_READ_REG(hw, MPRC); ++ adapter->stats.roc += E1000_READ_REG(hw, ROC); ++ adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); ++ adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); ++ adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); ++ adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); ++ adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); ++ adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); ++ ++ adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); ++ adapter->stats.mpc += E1000_READ_REG(hw, MPC); ++ adapter->stats.scc += E1000_READ_REG(hw, SCC); ++ adapter->stats.ecol += E1000_READ_REG(hw, ECOL); ++ adapter->stats.mcc += E1000_READ_REG(hw, MCC); ++ adapter->stats.latecol += E1000_READ_REG(hw, LATECOL); ++ adapter->stats.dc += E1000_READ_REG(hw, DC); ++ adapter->stats.sec += E1000_READ_REG(hw, SEC); ++ adapter->stats.rlec += E1000_READ_REG(hw, RLEC); ++ adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC); ++ adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC); ++ adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC); ++ adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); ++ adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); ++ adapter->stats.gptc += E1000_READ_REG(hw, GPTC); ++ adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); ++ adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); ++ adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); ++ adapter->stats.ruc += E1000_READ_REG(hw, RUC); ++ adapter->stats.rfc += E1000_READ_REG(hw, RFC); ++ adapter->stats.rjc += E1000_READ_REG(hw, RJC); ++ adapter->stats.torl += E1000_READ_REG(hw, TORL); ++ adapter->stats.torh += E1000_READ_REG(hw, TORH); ++ adapter->stats.totl += E1000_READ_REG(hw, TOTL); ++ adapter->stats.toth += E1000_READ_REG(hw, TOTH); ++ adapter->stats.tpr += E1000_READ_REG(hw, TPR); ++ adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); ++ adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); ++ adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); ++ adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); ++ adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); ++ adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); ++ adapter->stats.mptc += E1000_READ_REG(hw, MPTC); ++ adapter->stats.bptc += E1000_READ_REG(hw, BPTC); ++ ++ /* used for adaptive IFS */ ++ ++ hw->tx_packet_delta = E1000_READ_REG(hw, TPT); ++ adapter->stats.tpt += hw->tx_packet_delta; ++ hw->collision_delta = E1000_READ_REG(hw, COLC); ++ adapter->stats.colc += hw->collision_delta; ++ ++ if(hw->mac_type >= iegbe_82543) { ++ adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC); ++ adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC); ++ adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS); ++ adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR); ++ adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC); ++ adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC); ++ } ++ if(hw->mac_type > iegbe_82547_rev_2) { ++ adapter->stats.iac += E1000_READ_REG(hw, IAC); ++ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); ++ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); ++ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); ++ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); ++ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); ++ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); ++ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); ++ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); ++ } ++ ++ /* Fill out the OS statistics structure */ ++ ++ adapter->net_stats.rx_packets = adapter->stats.gprc; ++ adapter->net_stats.tx_packets = adapter->stats.gptc; ++ adapter->net_stats.rx_bytes = adapter->stats.gorcl; ++ adapter->net_stats.tx_bytes = adapter->stats.gotcl; ++ adapter->net_stats.multicast = adapter->stats.mprc; ++ adapter->net_stats.collisions = adapter->stats.colc; ++ ++ /* Rx Errors */ ++ ++ adapter->net_stats.rx_errors = adapter->stats.rxerrc + ++ adapter->stats.crcerrs + adapter->stats.algnerrc + ++ adapter->stats.rlec + adapter->stats.mpc + ++ adapter->stats.cexterr; ++ adapter->net_stats.rx_dropped = adapter->stats.mpc; ++ adapter->net_stats.rx_length_errors = adapter->stats.rlec; ++ adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; ++ adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; ++ adapter->net_stats.rx_fifo_errors = adapter->stats.mpc; ++ adapter->net_stats.rx_missed_errors = adapter->stats.mpc; ++ ++ /* Tx Errors */ ++ ++ adapter->net_stats.tx_errors = adapter->stats.ecol + ++ adapter->stats.latecol; ++ adapter->net_stats.tx_aborted_errors = adapter->stats.ecol; ++ adapter->net_stats.tx_window_errors = adapter->stats.latecol; ++ adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs; + +- /* Tx Dropped needs to be maintained elsewhere */ ++ /* Tx Dropped needs to be maintained elsewhere */ + +- /* Phy Stats */ ++ /* Phy Stats */ + +- if(hw->media_type == iegbe_media_type_copper ++ if(hw->media_type == iegbe_media_type_copper + || (hw->media_type == iegbe_media_type_oem + && iegbe_oem_phy_is_copper(&adapter->hw))) { +- if((adapter->link_speed == SPEED_1000) && +- (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { +- phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; +- adapter->phy_stats.idle_errors += phy_tmp; +- } ++ if((adapter->link_speed == SPEED_1000) && ++ (!iegbe_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { ++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; ++ adapter->phy_stats.idle_errors += phy_tmp; ++ } + +- if((hw->mac_type <= iegbe_82546) && +- (hw->phy_type == iegbe_phy_m88) && ++ if((hw->mac_type <= iegbe_82546) && ++ (hw->phy_type == iegbe_phy_m88) && + !iegbe_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) { +- adapter->phy_stats.receive_errors += phy_tmp; +- } ++ adapter->phy_stats.receive_errors += phy_tmp; ++ } + } + +- spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); + } + +-#ifdef CONFIG_E1000_MQ +-void +-iegbe_rx_schedule(void *data) ++/** ++ * iegbe_intr_msi - Interrupt Handler ++ * @irq: interrupt number ++ * @data: pointer to a network interface device structure ++ **/ ++ ++static irqreturn_t iegbe_intr_msi(int irq, void *data) + { +- struct net_device *poll_dev, *netdev = data; +- struct iegbe_adapter *adapter = netdev->priv; +- int this_cpu = get_cpu(); +- +- poll_dev = *per_cpu_ptr(adapter->cpu_netdev, this_cpu); +- if (poll_dev == NULL) { +- put_cpu(); +- return; ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); ++ if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { ++ hw->get_link_status = 1; ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + +- if (likely(netif_rx_schedule_prep(poll_dev))) { +- __netif_rx_schedule(poll_dev); +- } else { +- iegbe_irq_enable(adapter); +- } +- put_cpu(); +-} +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +-/* +- * Check for tx hang condition. This is the condition where a +- * decsriptor is in the hardware and hasn't been processed for a +- * while. This code is similar to the check in iegbe_clean_rx_irq() +- */ +-static void +-iegbe_tx_hang_check(struct iegbe_adapter *adapter, +- struct iegbe_tx_ring *tx_ring) +-{ +- struct net_device *netdev = adapter->netdev; +- unsigned int i; ++ if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + +- /* Check for a hang condition using the buffer currently at the Tx +- head pointer */ +- i = readl(adapter->hw.hw_addr + tx_ring->tdh); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[tdh]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " jiffies <%lx>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- tx_ring->next_to_clean, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- jiffies); +- netif_stop_queue(netdev); +- } ++ iegbe_irq_disable(adapter); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-} ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ iegbe_irq_enable(adapter); + +-#endif ++ return IRQ_HANDLED; ++} + + /** + * iegbe_intr - Interrupt Handler +@@ -3546,364 +3478,208 @@ iegbe_tx_hang_check(struct iegbe_adapter + **/ + + static irqreturn_t +-iegbe_intr(int irq, void *data, struct pt_regs *regs) ++iegbe_intr(int irq, void *data) + { +- struct net_device *netdev = data; +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct iegbe_hw *hw = &adapter->hw; +- uint32_t rctl, tctl; +- uint32_t icr = E1000_READ_REG(hw, ICR); +-#ifndef CONFIG_E1000_NAPI +- uint32_t i; +-#ifdef IEGBE_GBE_WORKAROUND +- int rx_cleaned; +-#endif +-#endif ++ struct net_device *netdev = data; ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct iegbe_hw *hw = &adapter->hw; ++ u32 icr = E1000_READ_REG(&adapter->hw, ICR); + +- if(unlikely(!icr)) { ++ if (unlikely(!icr)) + return IRQ_NONE; /* Not our interrupt */ +- } ++ ++ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is ++ * not set, then the adapter didn't send an interrupt */ ++ if (unlikely(hw->mac_type >= iegbe_82571 && ++ !(icr & E1000_ICR_INT_ASSERTED))) ++ return IRQ_NONE; ++ ++ + if(unlikely(icr & (E1000_ICR_RX_DESC_FIFO_PAR +- | E1000_ICR_TX_DESC_FIFO_PAR +- | E1000_ICR_PB +- | E1000_ICR_CPP_TARGET +- | E1000_ICR_CPP_MASTER ))) { ++ | E1000_ICR_TX_DESC_FIFO_PAR ++ | E1000_ICR_PB ++ | E1000_ICR_CPP_TARGET ++ | E1000_ICR_CPP_MASTER ))) { + + iegbe_irq_disable(adapter); +- tctl = E1000_READ_REG(&adapter->hw, TCTL); +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_TCTL_EN); +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN); +- +- tasklet_data = (unsigned long) (icr + adapter->bd_number); +- tasklet_schedule(&iegbe_reset_tasklet); +- +- return IRQ_HANDLED; +- } +- +-#ifdef CONFIG_E1000_NAPI +- atomic_inc(&adapter->irq_sem); +-#ifdef IEGBE_GBE_WORKAROUND +- /* Ensure that the TXQE interrupt is enabled in NAPI mode */ +- E1000_WRITE_REG(hw, IMC, ~E1000_IMS_TXQE); +-#else +- E1000_WRITE_REG(hw, IMC, ~0); +-#endif +- E1000_WRITE_FLUSH(hw); +-#ifdef CONFIG_E1000_MQ +- if (atomic_read(&adapter->rx_sched_call_data.count) == 0) { +- cpu_set(adapter->cpu_for_queue[0], +- adapter->rx_sched_call_data.cpumask); +- for (i = 1; i < adapter->num_queues; i++) { +- cpu_set(adapter->cpu_for_queue[i], +- adapter->rx_sched_call_data.cpumask); +- atomic_inc(&adapter->irq_sem); +- } +- atomic_set(&adapter->rx_sched_call_data.count, i); +- smp_call_async_mask(&adapter->rx_sched_call_data); +- } else { +- DEBUGOUT("call_data.count == %u\n", +- atomic_read(&adapter->rx_sched_call_data.count)); ++ printk("Critical error! ICR = 0x%x\n", icr); ++ return IRQ_HANDLED; + } +-#else +- if (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) { +- __netif_rx_schedule(&adapter->polling_netdev[0]); +- } else { +- iegbe_irq_enable(adapter); +- } +-#endif +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Clean the Tx ring */ +- for (i = 0; i < E1000_MAX_INTR; i++) { +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- } + +-#endif /*IEGBE_GBE_WORKAROUND */ +- +-#else +- /* Writing IMC and IMS is needed for 82547. +- * Due to Hub Link bus being occupied, an interrupt +- * de-assertion message is not able to be sent. +- * When an interrupt assertion message is generated later, +- * two messages are re-ordered and sent out. +- * That causes APIC to think 82547 is in de-assertion +- * state, while 82547 is in assertion state, resulting +- * in dead lock. Writing IMC forces 82547 into +- * de-assertion state. +- */ +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- atomic_inc(&adapter->irq_sem); +- E1000_WRITE_REG(hw, IMC, ~0); +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- +- for (i = 0; i < E1000_MAX_INTR; i++) { +- rx_cleaned = adapter->clean_rx(adapter, adapter->rx_ring); +- adapter->stats.rx_next_to_clean = adapter->rx_ring->next_to_clean; +- adapter->stats.rx_next_to_use = adapter->rx_ring->next_to_use; +- +- adapter->stats.tx_next_to_clean = adapter->tx_ring->next_to_clean; +- adapter->stats.tx_next_to_use = adapter->tx_ring->next_to_use; +- +- /* Only clean Tx descriptors for a TXQE interrupt */ +- if(icr & E1000_ICR_TXQE) { +- adapter->stats.txqec++; +- iegbe_clean_tx_ring_partial(adapter, adapter->tx_ring); +- } +- else { +- iegbe_tx_hang_check(adapter, adapter->tx_ring); +- } +- if(!rx_cleaned) { +- break; +- } ++ /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No ++ * need for the IMC write */ ++ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { ++ hw->get_link_status = 1; ++ /* guard against interrupt when we're going down */ ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ mod_timer(&adapter->watchdog_timer, jiffies + 1); ++ + } + +-#else +- for (i = 0; i < E1000_MAX_INTR; i++) +- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & +- !iegbe_clean_tx_irq(adapter, adapter->tx_ring))) { +- break; +- } +-#endif +- +- if (hw->mac_type == iegbe_82547 || hw->mac_type == iegbe_82547_rev_2) { +- iegbe_irq_enable(adapter); +- } +-#endif +-#ifdef E1000_COUNT_ICR +- adapter->icr_txdw += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_txqe += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_lsc += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxseq += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxdmt += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxo += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxt += icr & 0x01UL; +- if(hw->mac_type != iegbe_icp_xxxx) { +- icr >>= 0x2; +- adapter->icr_mdac += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_rxcfg += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_gpi += icr & 0x01UL; +- } else { +- icr >>= 0x4; +- } +- if(hw->mac_type == iegbe_icp_xxxx) { +- icr >>= 0xc; +- adapter->icr_pb += icr & 0x01UL; +- icr >>= 0x3; +- adapter->icr_intmem_icp_xxxx += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_target += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_cpp_master += icr & 0x01UL; +- icr >>= 0x1; +- adapter->icr_stat += icr & 0x01UL; ++ if (unlikely(hw->mac_type < iegbe_82571)) { ++ E1000_WRITE_REG(&adapter->hw, IMC, ~0); ++ E1000_WRITE_FLUSH(&adapter->hw); + } +-#endif ++ if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ adapter->total_tx_bytes = 0; ++ adapter->total_tx_packets = 0; ++ adapter->total_rx_bytes = 0; ++ adapter->total_rx_packets = 0; ++ __netif_rx_schedule(netdev, &adapter->napi); ++ } else ++ /* this really should not happen! if it does it is basically a ++ * bug, but not a hard error, so enable ints and continue */ ++ iegbe_irq_enable(adapter); + + return IRQ_HANDLED; + } + +-#ifdef CONFIG_E1000_NAPI + /** + * iegbe_clean - NAPI Rx polling callback + * @adapter: board private structure + **/ +- +-static int +-iegbe_clean(struct net_device *poll_dev, int *budget) ++static int iegbe_clean(struct napi_struct *napi, int budget) + { +- struct iegbe_adapter *adapter; +- int work_to_do = min(*budget, poll_dev->quota); +- int tx_cleaned, i = 0, work_done = 0; ++ struct iegbe_adapter *adapter = container_of(napi, struct iegbe_adapter, napi); ++ struct net_device *poll_dev = adapter->netdev; ++ int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ + adapter = poll_dev->priv; + +- /* Keep link state information with original netdev */ +- if (!netif_carrier_ok(adapter->netdev)) { +- goto quit_polling; +- } +- while (poll_dev != &adapter->polling_netdev[i]) { +- i++; +- if (unlikely(i == adapter->num_queues)) { +- BUG(); +- } +- } +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Tx descriptors are cleaned in iegbe_intr(). No need to clean +- them here */ +- tx_cleaned = FALSE; +-#else +- tx_cleaned = iegbe_clean_tx_irq(adapter, &adapter->tx_ring[i]); +-#endif +- adapter->clean_rx(adapter, &adapter->rx_ring[i], +- &work_done, work_to_do); +- +- *budget -= work_done; +- poll_dev->quota -= work_done; +- +- /* If no Tx and not enough Rx work done, exit the polling mode */ +- if((!tx_cleaned && (work_done == 0)) || +- !netif_running(adapter->netdev)) { +-quit_polling: +- netif_rx_complete(poll_dev); ++ /* iegbe_clean is called per-cpu. This lock protects ++ * tx_ring[0] from being cleaned by multiple cpus ++ * simultaneously. A failure obtaining the lock means ++ * tx_ring[0] is currently being cleaned anyway. */ ++ if (spin_trylock(&adapter->tx_queue_lock)) { ++ tx_cleaned = iegbe_clean_tx_irq(adapter, ++ &adapter->tx_ring[0]); ++ spin_unlock(&adapter->tx_queue_lock); ++ } ++ ++ adapter->clean_rx(adapter, &adapter->rx_ring[0], ++ &work_done, budget); ++ ++ if (tx_cleaned) ++ work_done = budget; ++ ++ /* If budget not fully consumed, exit the polling mode */ ++ if (work_done < budget) { ++ if (likely(adapter->itr_setting & 3)) ++ iegbe_set_itr(adapter); ++ netif_rx_complete(poll_dev, napi); + iegbe_irq_enable(adapter); +- return 0; + } + +- return 1; ++ return work_done; + } + +-#endif +- +- +-#ifndef IEGBE_GBE_WORKAROUND + /** + * iegbe_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + **/ +- +-static boolean_t +-iegbe_clean_tx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_tx_irq(struct iegbe_adapter *adapter, + struct iegbe_tx_ring *tx_ring) + { +- struct net_device *netdev = adapter->netdev; +- struct iegbe_tx_desc *tx_desc, *eop_desc; +- struct iegbe_buffer *buffer_info; +- unsigned int i, eop; +- boolean_t cleaned = FALSE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct iegbe_tx_desc *tx_desc, *eop_desc; ++ struct iegbe_buffer *buffer_info; ++ unsigned int i, eop; ++ unsigned int count = 0; ++ bool cleaned = false; ++ unsigned int total_tx_bytes=0, total_tx_packets=0; + +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); ++ i = tx_ring->next_to_clean; ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); + + while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { +- /* Premature writeback of Tx descriptors clear (free buffers +- * and unmap pci_mapping) previous_buffer_info */ +- if (likely(tx_ring->previous_buffer_info.skb != NULL)) { +- iegbe_unmap_and_free_tx_resource(adapter, +- &tx_ring->previous_buffer_info); +- } +- +- for (cleaned = FALSE; !cleaned; ) { +- tx_desc = E1000_TX_DESC(*tx_ring, i); +- buffer_info = &tx_ring->buffer_info[i]; +- cleaned = (i == eop); +- +-#ifdef NETIF_F_TSO +- if (!(netdev->features & NETIF_F_TSO)) { +-#endif +- iegbe_unmap_and_free_tx_resource(adapter, +- buffer_info); +-#ifdef NETIF_F_TSO +- } else { +- if (cleaned) { +- memcpy(&tx_ring->previous_buffer_info, +- buffer_info, +- sizeof(struct iegbe_buffer)); +- memset(buffer_info, 0, +- sizeof(struct iegbe_buffer)); +- } else { +- iegbe_unmap_and_free_tx_resource( +- adapter, buffer_info); +- } +- } +-#endif +- +- tx_desc->buffer_addr = 0; +- tx_desc->lower.data = 0; ++ for (cleaned = false; !cleaned; ) { ++ tx_desc = E1000_TX_DESC(*tx_ring, i); ++ buffer_info = &tx_ring->buffer_info[i]; ++ cleaned = (i == eop); ++ ++ if (cleaned) { ++ struct sk_buff *skb = buffer_info->skb; ++ unsigned int segs = 0, bytecount; ++ segs = skb_shinfo(skb)->gso_segs ?: 1; ++ bytecount = ((segs - 1) * skb_headlen(skb)) + ++ skb->len; ++ total_tx_packets += segs; ++ total_tx_bytes += bytecount; ++ } ++ iegbe_unmap_and_free_tx_resource(adapter, buffer_info); + tx_desc->upper.data = 0; + +- if (unlikely(++i == tx_ring->count)) { i = 0; } +- } +- +- tx_ring->pkt++; ++ if (unlikely(++i == tx_ring->count)) i = 0; ++ } + +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- } ++ eop = tx_ring->buffer_info[i].next_to_watch; ++ eop_desc = E1000_TX_DESC(*tx_ring, eop); ++#define E1000_TX_WEIGHT 64 ++ /* weight of a sort for tx, to avoid endless transmit cleanup */ ++ if (count++ == E1000_TX_WEIGHT) ++ break; ++ } + + tx_ring->next_to_clean = i; + +- spin_lock(&tx_ring->tx_lock); ++#define TX_WAKE_THRESHOLD 32 + +- if (unlikely(cleaned && netif_queue_stopped(netdev) && +- netif_carrier_ok(netdev))) { +- netif_wake_queue(netdev); +- } +- spin_unlock(&tx_ring->tx_lock); +- +- if (adapter->detect_tx_hung) { +- /* Detect a transmit hang in hardware, this serializes the +- * check with the clearing of time_stamp and movement of i */ +- adapter->detect_tx_hung = FALSE; +- +- if (tx_ring->buffer_info[i].dma && +- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) +- && !(E1000_READ_REG(&adapter->hw, STATUS) & +- E1000_STATUS_TXOFF)) { +- +- /* detected Tx unit hang */ +- i = tx_ring->next_to_clean; +- eop = tx_ring->buffer_info[i].next_to_watch; +- eop_desc = E1000_TX_DESC(*tx_ring, eop); +- DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" +- " TDH <%x>\n" +- " TDT <%x>\n" +- " next_to_use <%x>\n" +- " next_to_clean <%x>\n" +- "buffer_info[next_to_clean]\n" +- " dma <%zx>\n" +- " time_stamp <%lx>\n" +- " next_to_watch <%x>\n" +- " jiffies <%lx>\n" +- " next_to_watch.status <%x>\n", +- readl(adapter->hw.hw_addr + tx_ring->tdh), +- readl(adapter->hw.hw_addr + tx_ring->tdt), +- tx_ring->next_to_use, +- i, +- (size_t)tx_ring->buffer_info[i].dma, +- tx_ring->buffer_info[i].time_stamp, +- eop, +- jiffies, +- eop_desc->upper.fields.status); +- netif_stop_queue(netdev); ++ if (unlikely(cleaned && netif_carrier_ok(netdev) && ++ E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { ++ /* Make sure that anybody stopping the queue after this ++ * sees the new next_to_clean. ++ */ ++ smp_mb(); ++ if (netif_queue_stopped(netdev)) { ++ netif_wake_queue(netdev); ++ ++adapter->restart_queue; + } + } +-#ifdef NETIF_F_TSO +- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && +- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ))) { +- iegbe_unmap_and_free_tx_resource( +- adapter, &tx_ring->previous_buffer_info); ++ ++ if (adapter->detect_tx_hung) { ++ /* Detect a transmit hang in hardware, this serializes the ++ * check with the clearing of time_stamp and movement of i */ ++ adapter->detect_tx_hung = false; ++ ++ if (tx_ring->buffer_info[eop].dma && ++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + ++ (adapter->tx_timeout_factor * HZ)) ++ && !(E1000_READ_REG(hw, STATUS) & E1000_STATUS_TXOFF)) { ++ ++ /* detected Tx unit hang */ ++ DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" ++ " Tx Queue <%lu>\n" ++ " TDH <%x>\n" ++ " TDT <%x>\n" ++ " next_to_use <%x>\n" ++ " next_to_clean <%x>\n" ++ "buffer_info[next_to_clean]\n" ++ " time_stamp <%lx>\n" ++ " next_to_watch <%x>\n" ++ " jiffies <%lx>\n" ++ " next_to_watch.status <%x>\n", ++ (unsigned long)((tx_ring - adapter->tx_ring) / ++ sizeof(struct iegbe_tx_ring)), ++ readl(hw->hw_addr + tx_ring->tdh), ++ readl(hw->hw_addr + tx_ring->tdt), ++ tx_ring->next_to_use, ++ tx_ring->next_to_clean, ++ tx_ring->buffer_info[eop].time_stamp, ++ eop, ++ jiffies, ++ eop_desc->upper.fields.status); ++ netif_stop_queue(netdev); ++ } + } +-#endif +- return cleaned; ++ adapter->total_tx_bytes += total_tx_bytes; ++ adapter->total_tx_packets += total_tx_packets; ++ adapter->net_stats.tx_bytes += total_tx_bytes; ++ adapter->net_stats.tx_packets += total_tx_packets; ++ return cleaned; + } +-#endif + + /** + * iegbe_rx_checksum - Receive Checksum Offload for 82543 +@@ -3913,192 +3689,193 @@ iegbe_clean_tx_irq(struct iegbe_adapter + * @sk_buff: socket buffer with received data + **/ + +-static inline void +-iegbe_rx_checksum(struct iegbe_adapter *adapter, +- uint32_t status_err, uint32_t csum, +- struct sk_buff *skb) ++static void iegbe_rx_checksum(struct iegbe_adapter *adapter, u32 status_err, ++ u32 csum, struct sk_buff *skb) + { +- uint16_t status = (uint16_t)status_err; +- uint8_t errors = (uint8_t)(status_err >> 0x18); ++ struct iegbe_hw *hw = &adapter->hw; ++ u16 status = (u16)status_err; ++ u8 errors = (u8)(status_err >> 24); + skb->ip_summed = CHECKSUM_NONE; + +- /* 82543 or newer only */ +- if(unlikely(adapter->hw.mac_type < iegbe_82543)) { return; } +- /* Ignore Checksum bit is set */ +- if(unlikely(status & E1000_RXD_STAT_IXSM)) { return; } +- /* TCP/UDP checksum error bit is set */ +- if(unlikely(errors & E1000_RXD_ERR_TCPE)) { +- /* let the stack verify checksum errors */ +- adapter->hw_csum_err++; +- return; +- } +- /* TCP/UDP Checksum has not been calculated */ +- if(adapter->hw.mac_type <= iegbe_82547_rev_2) { +- if(!(status & E1000_RXD_STAT_TCPCS)) { +- return; ++ /* 82543 or newer only */ ++ if (unlikely(hw->mac_type < iegbe_82543)) return; ++ /* Ignore Checksum bit is set */ ++ if (unlikely(status & E1000_RXD_STAT_IXSM)) return; ++ /* TCP/UDP checksum error bit is set */ ++ if(unlikely(errors & E1000_RXD_ERR_TCPE)) { ++ /* let the stack verify checksum errors */ ++ adapter->hw_csum_err++; ++ return; ++ } ++ /* TCP/UDP Checksum has not been calculated */ ++ if (hw->mac_type <= iegbe_82547_rev_2) { ++ if (!(status & E1000_RXD_STAT_TCPCS)) ++ return; ++ } else { ++ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) ++ return; + } +- } else { +- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) { +- return; +- } ++ /* It must be a TCP or UDP packet with a valid checksum */ ++ if(likely(status & E1000_RXD_STAT_TCPCS)) { ++ /* TCP checksum is good */ ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } else if (hw->mac_type > iegbe_82547_rev_2) { ++ /* IP fragment with UDP payload */ ++ /* Hardware complements the payload checksum, so we undo it ++ * and then put the value in host order for further stack use. ++ */ ++ __sum16 sum = (__force __sum16)htons(csum); ++ skb->csum = csum_unfold(~sum); ++ skb->ip_summed = CHECKSUM_COMPLETE; + } +- /* It must be a TCP or UDP packet with a valid checksum */ +- if(likely(status & E1000_RXD_STAT_TCPCS)) { +- /* TCP checksum is good */ +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- } else if(adapter->hw.mac_type > iegbe_82547_rev_2) { +- /* IP fragment with UDP payload */ +- /* Hardware complements the payload checksum, so we undo it +- * and then put the value in host order for further stack use. +- */ +- csum = ntohl(csum ^ 0xFFFF); +- skb->csum = csum; +- skb->ip_summed = CHECKSUM_HW; +- } +- adapter->hw_csum_good++; ++ adapter->hw_csum_good++; + } + + /** + * iegbe_clean_rx_irq - Send received data up the network stack; legacy + * @adapter: board private structure + **/ +- +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned long flags = 0; +- uint32_t length; +- uint8_t last_byte; +- unsigned int i; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- +- while(rx_desc->status & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +-#ifdef CONFIG_E1000_NAPI +- if(*work_done >= work_to_do) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc, *next_rxd; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ unsigned long flags; ++ u32 length; ++ u8 last_byte; ++ unsigned int i; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; + +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, +- buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(rx_desc->status & E1000_RXD_STAT_DD) { ++ struct sk_buff *skb; ++ u8 status; ++ if (*work_done >= work_to_do) ++ break; ++ (*work_done)++; + ++ status = rx_desc->status; + skb = buffer_info->skb; +- length = le16_to_cpu(rx_desc->length); ++ buffer_info->skb = NULL; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ length = le16_to_cpu(rx_desc->length); ++ ++ if (unlikely(!(status & E1000_RXD_STAT_EOP))) { ++ /* All receives must fit into a single buffer */ ++ E1000_DBG("%s: Receive packet consumed multiple" ++ " buffers\n", netdev->name); ++ buffer_info->skb = skb; ++ goto next_desc; ++ } + +- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) { +- /* All receives must fit into a single buffer */ +- E1000_DBG("%s: Receive packet consumed multiple" +- " buffers\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { ++ last_byte = *(skb->data + length - 1); ++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length, ++ last_byte)) { ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ iegbe_tbi_adjust_stats(hw, &adapter->stats, ++ length, skb->data); ++ spin_unlock_irqrestore(&adapter->stats_lock, ++ flags); ++ length--; ++ } else { ++ buffer_info->skb = skb; ++ goto next_desc; ++ } ++ } + +- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { +- last_byte = *(skb->data + length - 0x1); +- if(TBI_ACCEPT(&adapter->hw, rx_desc->status, +- rx_desc->errors, length, last_byte)) { +- spin_lock_irqsave(&adapter->stats_lock, flags); +- iegbe_tbi_adjust_stats(&adapter->hw, +- &adapter->stats, +- length, skb->data); +- spin_unlock_irqrestore(&adapter->stats_lock, +- flags); +- length--; +- } else { +- dev_kfree_skb_irq(skb); +- goto next_desc; ++ /* adjust length to remove Ethernet CRC, this must be ++ * done after the TBI_ACCEPT workaround above */ ++ length -= 4; ++ ++ /* probably a little skewed due to removing CRC */ ++ total_rx_bytes += length; ++ total_rx_packets++; ++ ++ /* code added for copybreak, this should improve ++ * performance for small packets with large amounts ++ * of reassembly being done in the stack */ ++ if (length < copybreak) { ++ struct sk_buff *new_skb = ++ netdev_alloc_skb(netdev, length + NET_IP_ALIGN); ++ if (new_skb) { ++ skb_reserve(new_skb, NET_IP_ALIGN); ++ skb_copy_to_linear_data_offset(new_skb, ++ -NET_IP_ALIGN, ++ (skb->data - ++ NET_IP_ALIGN), ++ (length + ++ NET_IP_ALIGN)); ++ /* save the skb in buffer_info as good */ ++ buffer_info->skb = skb; ++ skb = new_skb; + } ++ /* else just continue with the old one */ + } +- +- /* Good Receive */ +- skb_put(skb, length - ETHERNET_FCS_SIZE); ++ /* Good Receive */ ++ skb_put(skb, length); + + /* Receive Checksum Offload */ + iegbe_rx_checksum(adapter, +- (uint32_t)(rx_desc->status) | +- ((uint32_t)(rx_desc->errors) << 0x18), +- rx_desc->csum, skb); ++ (u32)(status) | ++ ((u32)(rx_desc->errors) << 24), ++ le16_to_cpu(rx_desc->csum), skb); ++ + skb->protocol = eth_type_trans(skb, netdev); +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { ++ ++ if (unlikely(adapter->vlgrp && ++ (status & E1000_RXD_STAT_VP))) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); ++ le16_to_cpu(rx_desc->special)); + } else { + netif_receive_skb(skb); + } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && +- (rx_desc->status & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ ++ + netdev->last_rx = jiffies; +- rx_ring->pkt++; + + next_desc: + rx_desc->status = 0; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } + +- rx_desc = E1000_RX_DESC(*rx_ring, i); ++ /* return some buffers to hardware, one at a time is too slow */ ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; + } + rx_ring->next_to_clean = i; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif +- ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; + return cleaned; + } + +@@ -4107,161 +3884,153 @@ next_desc: + * @adapter: board private structure + **/ + +-static boolean_t +-#ifdef CONFIG_E1000_NAPI +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, ++static bool iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int *work_done, int work_to_do) +-#else +-iegbe_clean_rx_irq_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- union iegbe_rx_desc_packet_split *rx_desc; +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- uint32_t length, staterr; +- boolean_t cleaned = FALSE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- /* Need to keep track of the amount of Rx descriptors that we +- cleaned to ensure that we don't supply too many back to the +- hardware */ +- int cleaned_count = 0; +-#endif +- +- i = rx_ring->next_to_clean; +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- +- while(staterr & E1000_RXD_STAT_DD) { +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; +-#ifdef CONFIG_E1000_NAPI +- if(unlikely(*work_done >= work_to_do)) { +- break; +- } +- (*work_done)++; +-#endif +- cleaned = TRUE; +- +-#ifdef IEGBE_GBE_WORKAROUND +- cleaned_count++; +-#endif ++ union iegbe_rx_desc_packet_split *rx_desc, *next_rxd; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_buffer *buffer_info, *next_buffer; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ u32 length, staterr; ++ int cleaned_count = 0; ++ bool cleaned = false; ++ unsigned int total_rx_bytes=0, total_rx_packets=0; ++ ++ i = rx_ring->next_to_clean; ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ buffer_info = &rx_ring->buffer_info[i]; + +- pci_unmap_single(pdev, buffer_info->dma, +- buffer_info->length, +- PCI_DMA_FROMDEVICE); ++ while(staterr & E1000_RXD_STAT_DD) { ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; ++ ++ if (unlikely(*work_done >= work_to_do)) ++ break; ++ (*work_done)++; + + skb = buffer_info->skb; ++ prefetch(skb->data - NET_IP_ALIGN); ++ if (++i == rx_ring->count) i = 0; ++ next_rxd = E1000_RX_DESC_PS(*rx_ring, i); ++ prefetch(next_rxd); ++ next_buffer = &rx_ring->buffer_info[i]; ++ cleaned = true; ++ cleaned_count++; ++ pci_unmap_single(pdev, buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_FROMDEVICE); ++ ++ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { ++ E1000_DBG("%s: Packet Split buffers didn't pick up" ++ " the full packet\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) { +- E1000_DBG("%s: Packet Split buffers didn't pick up" +- " the full packet\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } +- +- length = le16_to_cpu(rx_desc->wb.middle.length0); ++ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- if(unlikely(!length)) { +- E1000_DBG("%s: Last part of the packet spanning" +- " multiple descriptors\n", netdev->name); +- dev_kfree_skb_irq(skb); +- goto next_desc; +- } ++ length = le16_to_cpu(rx_desc->wb.middle.length0); + +- /* Good Receive */ +- skb_put(skb, length); +- +- for(j = 0; j < adapter->rx_ps_pages; j++) { +- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j]))) { +- break; +- } +- pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], +- PAGE_SIZE, PCI_DMA_FROMDEVICE); +- ps_page_dma->ps_page_dma[j] = 0; +- skb_shinfo(skb)->frags[j].page = +- ps_page->ps_page[j]; +- ps_page->ps_page[j] = NULL; +- skb_shinfo(skb)->frags[j].page_offset = 0; +- skb_shinfo(skb)->frags[j].size = length; +- skb_shinfo(skb)->nr_frags++; +- skb->len += length; +- skb->data_len += length; +- } ++ if(unlikely(!length)) { ++ E1000_DBG("%s: Last part of the packet spanning" ++ " multiple descriptors\n", netdev->name); ++ dev_kfree_skb_irq(skb); ++ goto next_desc; ++ } + +- iegbe_rx_checksum(adapter, staterr, +- rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); +- skb->protocol = eth_type_trans(skb, netdev); ++ /* Good Receive */ ++ skb_put(skb, length); + +- if(likely(rx_desc->wb.upper.header_status & +- E1000_RXDPS_HDRSTAT_HDRSP)) { +- adapter->rx_hdr_split++; +-#ifdef HAVE_RX_ZERO_COPY +- skb_shinfo(skb)->zero_copy = TRUE; +-#endif +- } +-#ifdef CONFIG_E1000_NAPI +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_receive_skb(skb); +- } +-#else +- netif_receive_skb(skb); +-#endif +-#else /* CONFIG_E1000_NAPI */ +-#ifdef NETIF_F_HW_VLAN_TX +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_rx(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan) & +- E1000_RXD_SPC_VLAN_MASK); +- } else { +- netif_rx(skb); +- } +-#else +- netif_rx(skb); +-#endif +-#endif /* CONFIG_E1000_NAPI */ +- netdev->last_rx = jiffies; +- rx_ring->pkt++; ++ { ++ int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); ++ if (l1 && (l1 <= copybreak) && ((length + l1) <= adapter->rx_ps_bsize0)) { ++ u8 *vaddr; ++ pci_dma_sync_single_for_cpu(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); ++ vaddr = kmap_atomic(ps_page->ps_page[0], ++ KM_SKB_DATA_SOFTIRQ); ++ memcpy(skb_tail_pointer(skb), vaddr, l1); ++ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ); ++ pci_dma_sync_single_for_device(pdev, ++ ps_page_dma->ps_page_dma[0], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ l1 -= 4; ++ skb_put(skb, l1); ++ goto copydone; ++ } /* if */ ++ } ++ for (j = 0; j < adapter->rx_ps_pages; j++) { ++ length = le16_to_cpu(rx_desc->wb.upper.length[j]); ++ if (!length) ++ break; ++ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j], ++ PAGE_SIZE, PCI_DMA_FROMDEVICE); ++ ps_page_dma->ps_page_dma[j] = 0; ++ skb_fill_page_desc(skb, j, ps_page->ps_page[j], 0, ++ length); ++ ps_page->ps_page[j] = NULL; ++ skb->len += length; ++ skb->data_len += length; ++ skb->truesize += length; ++ } + +-next_desc: +- rx_desc->wb.middle.status_error &= ~0xFF; +- buffer_info->skb = NULL; +- if(unlikely(++i == rx_ring->count)) { i = 0; } ++ pskb_trim(skb, skb->len - 4); ++copydone: ++ total_rx_bytes += skb->len; ++ total_rx_packets++; ++ iegbe_rx_checksum(adapter, staterr, ++ le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ if(likely(rx_desc->wb.upper.header_status & ++ cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) ++ adapter->rx_hdr_split++; ++ ++ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { ++ vlan_hwaccel_receive_skb(skb, adapter->vlgrp, ++ le16_to_cpu(rx_desc->wb.middle.vlan)); ++ } else { ++ netif_receive_skb(skb); ++ } + +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); +- staterr = le32_to_cpu(rx_desc->wb.middle.status_error); +- } +- rx_ring->next_to_clean = i; ++ netdev->last_rx = jiffies; + +-#ifdef IEGBE_GBE_WORKAROUND +- /* Only allocate the number of buffers that we have actually +- cleaned! */ +- if (cleaned_count) { +- adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); +- } +-#else +- adapter->alloc_rx_buf(adapter, rx_ring); +-#endif ++next_desc: ++ rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); ++ buffer_info->skb = NULL; + +- return cleaned; ++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ cleaned_count = 0; ++ } ++ ++ /* use prefetched values */ ++ rx_desc = next_rxd; ++ buffer_info = next_buffer; ++ staterr = le32_to_cpu(rx_desc->wb.middle.status_error); ++ } ++ rx_ring->next_to_clean = i; ++ ++ cleaned_count = E1000_DESC_UNUSED(rx_ring); ++ if (cleaned_count) ++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); ++ ++ adapter->total_rx_packets += total_rx_packets; ++ adapter->total_rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_bytes += total_rx_bytes; ++ adapter->net_stats.rx_packets += total_rx_packets; ++ return cleaned; + } + + /** +@@ -4269,142 +4038,115 @@ next_desc: + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- struct iegbe_rx_desc *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct sk_buff *skb; +- unsigned int i; +- unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ struct iegbe_rx_desc *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct sk_buff *skb; ++ unsigned int i; ++ unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN; + +-#ifdef IEGBE_GBE_WORKAROUND +- if (cleaned_count > IEGBE_GBE_WORKAROUND_NUM_RX_DESCRIPTORS) { +- adapter->stats.cc_gt_num_rx++; +- } +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- skb = dev_alloc_skb(bufsz); ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; + +- if(unlikely(!skb)) { +- /* Better luck next round */ +- break; +- } ++ while (cleaned_count--) { ++ skb = buffer_info->skb; ++ if (skb) { ++ skb_trim(skb, 0); ++ goto map_skb; ++ } ++ skb = netdev_alloc_skb(netdev, bufsz); ++ ++ if(unlikely(!skb)) { ++ /* Better luck next round */ ++ adapter->alloc_rx_buff_failed++; ++ break; ++ } + +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- struct sk_buff *oldskb = skb; +- DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " +- "at %p\n", bufsz, skb->data); +- /* Try again, without freeing the previous */ +- skb = dev_alloc_skb(bufsz); +- /* Failed allocation, critical failure */ +- if(!skb) { +- dev_kfree_skb(oldskb); +- break; +- } ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ struct sk_buff *oldskb = skb; ++ DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " ++ "at %p\n", bufsz, skb->data); ++ /* Try again, without freeing the previous */ ++ skb = netdev_alloc_skb(netdev, bufsz); ++ /* Failed allocation, critical failure */ ++ if(!skb) { ++ dev_kfree_skb(oldskb); ++ break; ++ } + +- if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { +- /* give up */ +- dev_kfree_skb(skb); +- dev_kfree_skb(oldskb); +- break; /* while !buffer_info->skb */ +- } else { +- /* Use new allocation */ +- dev_kfree_skb(oldskb); ++ if(!iegbe_check_64k_bound(adapter, skb->data, bufsz)) { ++ /* give up */ ++ dev_kfree_skb(skb); ++ dev_kfree_skb(oldskb); ++ break; /* while !buffer_info->skb */ + } +- } +- /* Make buffer alignment 2 beyond a 16 byte boundary +- * this will result in a 16 byte aligned IP header after +- * the 14 byte MAC header is removed +- */ +- skb_reserve(skb, NET_IP_ALIGN); +- +- skb->dev = netdev; +- +- buffer_info->skb = skb; +- buffer_info->length = adapter->rx_buffer_len; +- buffer_info->dma = pci_map_single(pdev, +- skb->data, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- /* Fix for errata 23, can't cross 64kB boundary */ +- if(!iegbe_check_64k_bound(adapter, +- (void *)(unsigned long)buffer_info->dma, +- adapter->rx_buffer_len)) { +- DPRINTK(RX_ERR, ERR, +- "dma align check failed: %u bytes at %p\n", +- adapter->rx_buffer_len, +- (void *)(unsigned long)buffer_info->dma); +- dev_kfree_skb(skb); +- buffer_info->skb = NULL; +- +- pci_unmap_single(pdev, buffer_info->dma, +- adapter->rx_buffer_len, +- PCI_DMA_FROMDEVICE); +- +- break; /* while !buffer_info->skb */ +- } +- rx_desc = E1000_RX_DESC(*rx_ring, i); +- rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); +- +-#ifdef IEGBE_GBE_WORKAROUND_DISABLED +- adapter->stats.num_rx_buf_alloc++; ++ /* Use new allocation */ ++ dev_kfree_skb(oldskb); ++ } ++ /* Make buffer alignment 2 beyond a 16 byte boundary ++ * this will result in a 16 byte aligned IP header after ++ * the 14 byte MAC header is removed ++ */ ++ skb_reserve(skb, NET_IP_ALIGN); ++ ++ ++ buffer_info->skb = skb; ++ buffer_info->length = adapter->rx_buffer_len; ++map_skb: ++ buffer_info->dma = pci_map_single(pdev, ++ skb->data, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); ++ ++ /* Fix for errata 23, can't cross 64kB boundary */ ++ if(!iegbe_check_64k_bound(adapter, ++ (void *)(unsigned long)buffer_info->dma, ++ adapter->rx_buffer_len)) { ++ DPRINTK(RX_ERR, ERR, ++ "dma align check failed: %u bytes at %p\n", ++ adapter->rx_buffer_len, ++ (void *)(unsigned long)buffer_info->dma); ++ dev_kfree_skb(skb); ++ buffer_info->skb = NULL; ++ ++ pci_unmap_single(pdev, buffer_info->dma, ++ adapter->rx_buffer_len, ++ PCI_DMA_FROMDEVICE); + +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ break; /* while !buffer_info->skb */ ++ } ++ rx_desc = E1000_RX_DESC(*rx_ring, i); ++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + +-#endif +-#ifndef IEGBE_GBE_WORKAROUND +- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); +- } +-#endif +- if(unlikely(++i == rx_ring->count)) { i = 0; } +- buffer_info = &rx_ring->buffer_info[i]; +- } ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ if (unlikely(++i == rx_ring->count)) ++ i = 0; ++ buffer_info = &rx_ring->buffer_info[i]; ++ } + +-#ifdef IEGBE_GBE_WORKAROUND + if (likely(rx_ring->next_to_use != i)) { +- rx_ring->next_to_use = i; +- if (unlikely(i-- == 0)) { +- i = (rx_ring->count - 0x1); +- } ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) ++ i = (rx_ring->count - 1); ++ + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). */ + wmb(); +- writel(i, adapter->hw.hw_addr + rx_ring->rdt); ++ writel(i, hw->hw_addr + rx_ring->rdt); + } +-#else +- rx_ring->next_to_use = i; +-#endif + } + + /** +@@ -4412,49 +4154,41 @@ iegbe_alloc_rx_buffers(struct iegbe_adap + * @adapter: address of board private structure + **/ + +-#ifdef IEGBE_GBE_WORKAROUND +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, ++ ++static void iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, + struct iegbe_rx_ring *rx_ring, + int cleaned_count) +-#else +-static void +-iegbe_alloc_rx_buffers_ps(struct iegbe_adapter *adapter, +- struct iegbe_rx_ring *rx_ring) +-#endif + { +- struct net_device *netdev = adapter->netdev; +- struct pci_dev *pdev = adapter->pdev; +- union iegbe_rx_desc_packet_split *rx_desc; +- struct iegbe_buffer *buffer_info; +- struct iegbe_ps_page *ps_page; +- struct iegbe_ps_page_dma *ps_page_dma; +- struct sk_buff *skb; +- unsigned int i, j; +- +- i = rx_ring->next_to_use; +- buffer_info = &rx_ring->buffer_info[i]; +- ps_page = &rx_ring->ps_page[i]; +- ps_page_dma = &rx_ring->ps_page_dma[i]; ++ struct iegbe_hw *hw = &adapter->hw; ++ struct net_device *netdev = adapter->netdev; ++ struct pci_dev *pdev = adapter->pdev; ++ union iegbe_rx_desc_packet_split *rx_desc; ++ struct iegbe_buffer *buffer_info; ++ struct iegbe_ps_page *ps_page; ++ struct iegbe_ps_page_dma *ps_page_dma; ++ struct sk_buff *skb; ++ unsigned int i, j; ++ ++ i = rx_ring->next_to_use; ++ buffer_info = &rx_ring->buffer_info[i]; ++ ps_page = &rx_ring->ps_page[i]; ++ ps_page_dma = &rx_ring->ps_page_dma[i]; + +-#ifdef IEGBE_GBE_WORKAROUND +- while(cleaned_count-- && !buffer_info->skb) { +-#else +- while(!buffer_info->skb) { +-#endif +- rx_desc = E1000_RX_DESC_PS(*rx_ring, i); ++ while (cleaned_count--) { ++ rx_desc = E1000_RX_DESC_PS(*rx_ring, i); + + for (j = 0; j < PS_PAGE_BUFFERS; j++) { +- if (j < adapter->rx_ps_pages) { +- if (likely(!ps_page->ps_page[j])) { +- ps_page->ps_page[j] = +- alloc_page(GFP_ATOMIC); ++ if (j < adapter->rx_ps_pages) { ++ if (likely(!ps_page->ps_page[j])) { ++ ps_page->ps_page[j] = ++ alloc_page(GFP_ATOMIC); + if (unlikely(!ps_page->ps_page[j])) { +- goto no_buffers; ++ adapter->alloc_rx_buff_failed++; ++ goto no_buffers; + } +- ps_page_dma->ps_page_dma[j] = +- pci_map_page(pdev, +- ps_page->ps_page[j], ++ ps_page_dma->ps_page_dma[j] = ++ pci_map_page(pdev, ++ ps_page->ps_page[j], + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + } +@@ -4462,26 +4196,26 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + * change because each write-back erases + * this info. + */ +- rx_desc->read.buffer_addr[j+0x1] = ++ rx_desc->read.buffer_addr[j+1] = + cpu_to_le64(ps_page_dma->ps_page_dma[j]); +- } else { +- rx_desc->read.buffer_addr[j+0x1] = ~0; +- } ++ } else ++ rx_desc->read.buffer_addr[j+1] = ~cpu_to_le64(0); + } + +- skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); ++ skb = netdev_alloc_skb(netdev, ++ adapter->rx_ps_bsize0 + NET_IP_ALIGN); + +- if (unlikely(!skb)) { ++ if (unlikely(!skb)) { ++ adapter->alloc_rx_buff_failed++; + break; +- } ++ } ++ + /* Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + +- skb->dev = netdev; +- + buffer_info->skb = skb; + buffer_info->length = adapter->rx_ps_bsize0; + buffer_info->dma = pci_map_single(pdev, skb->data, +@@ -4490,27 +4224,28 @@ iegbe_alloc_rx_buffers_ps(struct iegbe_a + + rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); + +- if (unlikely((i & ~(E1000_RX_BUFFER_WRITE - 0x1)) == i)) { +- /* Force memory writes to complete before letting h/w +- * know there are new descriptors to fetch. (Only +- * applicable for weak-ordered memory model archs, +- * such as IA-64). */ +- wmb(); +- /* Hardware increments by 16 bytes, but packet split +- * descriptors are 32 bytes...so we increment tail +- * twice as much. +- */ +- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt); +- } +- +- if (unlikely(++i == rx_ring->count)) { i = 0; } ++ if (unlikely(++i == rx_ring->count)) i = 0; + buffer_info = &rx_ring->buffer_info[i]; + ps_page = &rx_ring->ps_page[i]; + ps_page_dma = &rx_ring->ps_page_dma[i]; + } + + no_buffers: +- rx_ring->next_to_use = i; ++ if (likely(rx_ring->next_to_use != i)) { ++ rx_ring->next_to_use = i; ++ if (unlikely(i-- == 0)) i = (rx_ring->count - 1); ++ ++ /* Force memory writes to complete before letting h/w ++ * know there are new descriptors to fetch. (Only ++ * applicable for weak-ordered memory model archs, ++ * such as IA-64). */ ++ wmb(); ++ /* Hardware increments by 16 bytes, but packet split ++ * descriptors are 32 bytes...so we increment tail ++ * twice as much. ++ */ ++ writel(i<<1, hw->hw_addr + rx_ring->rdt); ++ } + } + + /** +@@ -4521,52 +4256,52 @@ no_buffers: + static void + iegbe_smartspeed(struct iegbe_adapter *adapter) + { +- uint16_t phy_status; +- uint16_t phy_ctrl; ++ uint16_t phy_status; ++ uint16_t phy_ctrl; + +- if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || ++ if((adapter->hw.phy_type != iegbe_phy_igp) || !adapter->hw.autoneg || + !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) { +- return; ++ return; + } +- if(adapter->smartspeed == 0) { +- /* If Master/Slave config fault is asserted twice, +- * we assume back-to-back */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ if(adapter->smartspeed == 0x0) { ++ /* If Master/Slave config fault is asserted twice, ++ * we assume back-to-back */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) { return; } +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- if(phy_ctrl & CR_1000T_MS_ENABLE) { +- phy_ctrl &= ~CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, +- phy_ctrl); +- adapter->smartspeed++; +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, +- &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, +- phy_ctrl); +- } +- } +- return; +- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { +- /* If still no link, perhaps using 2/3 pair cable */ +- iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); +- phy_ctrl |= CR_1000T_MS_ENABLE; +- iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); +- if(!iegbe_phy_setup_autoneg(&adapter->hw) && +- !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { +- phy_ctrl |= (MII_CR_AUTO_NEG_EN | +- MII_CR_RESTART_AUTO_NEG); +- iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); +- } +- } +- /* Restart process after E1000_SMARTSPEED_MAX iterations */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ if(phy_ctrl & CR_1000T_MS_ENABLE) { ++ phy_ctrl &= ~CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, ++ phy_ctrl); ++ adapter->smartspeed++; ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, ++ &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, ++ phy_ctrl); ++ } ++ } ++ return; ++ } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { ++ /* If still no link, perhaps using 2/3 pair cable */ ++ iegbe_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); ++ phy_ctrl |= CR_1000T_MS_ENABLE; ++ iegbe_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); ++ if(!iegbe_phy_setup_autoneg(&adapter->hw) && ++ !iegbe_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { ++ phy_ctrl |= (MII_CR_AUTO_NEG_EN | ++ MII_CR_RESTART_AUTO_NEG); ++ iegbe_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); ++ } ++ } ++ /* Restart process after E1000_SMARTSPEED_MAX iterations */ + if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) { +- adapter->smartspeed = 0; +-} ++ adapter->smartspeed = 0x0; ++ } + } + + /** +@@ -4576,23 +4311,22 @@ iegbe_smartspeed(struct iegbe_adapter *a + * @cmd: + **/ + +-static int +-iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) + { +- switch (cmd) { ++ switch (cmd) { + #ifdef SIOCGMIIPHY +- case SIOCGMIIPHY: +- case SIOCGMIIREG: +- case SIOCSMIIREG: +- return iegbe_mii_ioctl(netdev, ifr, cmd); ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return iegbe_mii_ioctl(netdev, ifr, cmd); + #endif + #ifdef ETHTOOL_OPS_COMPAT +- case SIOCETHTOOL: +- return ethtool_ioctl(ifr); ++ case SIOCETHTOOL: ++ return ethtool_ioctl(ifr); + #endif +- default: +- return -EOPNOTSUPP; +- } ++ default: ++ return -EOPNOTSUPP; ++ } + } + + #ifdef SIOCGMIIPHY +@@ -4603,534 +4337,510 @@ iegbe_ioctl(struct net_device *netdev, s + * @cmd: + **/ + +-static int +-iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++static int iegbe_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, ++ int cmd) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- struct mii_ioctl_data *data = if_mii(ifr); +- int retval; +- uint16_t mii_reg; +- uint16_t spddplx; +- unsigned long flags; +- +- if((adapter->hw.media_type == iegbe_media_type_oem && +- !iegbe_oem_phy_is_copper(&adapter->hw)) || +- adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes ) { +- return -EOPNOTSUPP; +- } +- switch (cmd) { +- case SIOCGMIIPHY: +- data->phy_id = adapter->hw.phy_addr; +- break; +- case SIOCGMIIREG: ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ struct mii_ioctl_data *data = if_mii(ifr); ++ int retval; ++ uint16_t mii_reg; ++ uint16_t spddplx; ++ unsigned long flags = 0; ++ ++ if((adapter->hw.media_type == iegbe_media_type_oem ++ && !iegbe_oem_phy_is_copper(&adapter->hw)) ++ ||adapter->hw.media_type != iegbe_media_type_copper) { ++ return -EOPNOTSUPP; ++ } ++ switch (cmd) { ++ case SIOCGMIIPHY: ++ data->phy_id = adapter->hw.phy_addr; ++ break; ++ case SIOCGMIIREG: + if(!capable(CAP_NET_ADMIN)) { +- return -EPERM; ++ return -EPERM; + } +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, +- &data->val_out)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- case SIOCSMIIREG: ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, ++ &data->val_out)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ case SIOCSMIIREG: + if(!capable(CAP_NET_ADMIN)){ +- return -EPERM; ++ return -EPERM; + } + if(data->reg_num & ~(0x1F)) { +- return -EFAULT; ++ return -EFAULT; + } +- mii_reg = data->val_in; +- spin_lock_irqsave(&adapter->stats_lock, flags); +- if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, +- mii_reg)) { +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- return -EIO; +- } +- switch(adapter->hw.phy_type) { +- case iegbe_phy_m88: +- switch (data->reg_num) { +- case PHY_CTRL: ++ mii_reg = data->val_in; ++ spin_lock_irqsave(&adapter->stats_lock, flags); ++ if(iegbe_write_phy_reg(&adapter->hw, data->reg_num, ++ mii_reg)) { ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ return -EIO; ++ } ++ switch(adapter->hw.phy_type) { ++ case iegbe_phy_m88: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(mii_reg & MII_CR_AUTO_NEG_EN) { +- adapter->hw.autoneg = 1; +- adapter->hw.autoneg_advertised = 0x2F; +- } else { ++ if(mii_reg & MII_CR_AUTO_NEG_EN) { ++ adapter->hw.autoneg = 1; ++ adapter->hw.autoneg_advertised = 0x2F; ++ } else { + if(mii_reg & 0x40){ +- spddplx = SPEED_1000; ++ spddplx = SPEED_1000; + } else if(mii_reg & 0x2000) { +- spddplx = SPEED_100; ++ spddplx = SPEED_100; + } else { +- spddplx = SPEED_10; ++ spddplx = SPEED_10; + } +- spddplx += (mii_reg & 0x100) +- ? FULL_DUPLEX : +- HALF_DUPLEX; +- retval = iegbe_set_spd_dplx(adapter, +- spddplx); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, +- flags); +- return retval; +- } +- } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ spddplx += (mii_reg & 0x100) ++ ? FULL_DUPLEX : ++ HALF_DUPLEX; ++ retval = iegbe_set_spd_dplx(adapter, ++ spddplx); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, ++ flags); ++ return retval; ++ } ++ } ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- case M88E1000_PHY_SPEC_CTRL: +- case M88E1000_EXT_PHY_SPEC_CTRL: +- if(iegbe_phy_reset(&adapter->hw)) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return -EIO; +- } +- break; +- } +- break; ++ break; ++ case M88E1000_PHY_SPEC_CTRL: ++ case M88E1000_EXT_PHY_SPEC_CTRL: ++ if(iegbe_phy_reset(&adapter->hw)) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return -EIO; ++ } ++ break; ++ } ++ break; + +- case iegbe_phy_oem: +- retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); +- if(retval) { +- spin_unlock_irqrestore( +- &adapter->stats_lock, flags); +- return retval; +- } +- break; ++ case iegbe_phy_oem: ++ retval = iegbe_oem_mii_ioctl(adapter, flags, ifr, cmd); ++ if(retval) { ++ spin_unlock_irqrestore( ++ &adapter->stats_lock, flags); ++ return retval; ++ } ++ break; + +- default: +- switch (data->reg_num) { +- case PHY_CTRL: ++ default: ++ switch (data->reg_num) { ++ case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +- break; ++ break; + } +- if(netif_running(adapter->netdev)) { +- iegbe_down(adapter); +- iegbe_up(adapter); ++ if(netif_running(adapter->netdev)) { ++ iegbe_down(adapter); ++ iegbe_up(adapter); + } else { +- iegbe_reset(adapter); ++ iegbe_reset(adapter); + } +- break; +- } +- } +- spin_unlock_irqrestore(&adapter->stats_lock, flags); +- break; +- default: +- return -EOPNOTSUPP; +- } +- return E1000_SUCCESS; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&adapter->stats_lock, flags); ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return E1000_SUCCESS; + } + #endif + +-void +-iegbe_pci_set_mwi(struct iegbe_hw *hw) ++void iegbe_pci_set_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; +-#ifdef HAVE_PCI_SET_MWI +- int ret_val = pci_set_mwi(adapter->pdev); +- +- if(ret_val) { +- DPRINTK(PROBE, ERR, "Error in setting MWI\n"); +- } +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word | +- PCI_COMMAND_INVALIDATE); +-#endif ++ struct iegbe_adapter *adapter = hw->back; ++ int ret_val = pci_set_mwi(adapter->pdev); ++ ++ if (ret_val) ++ DPRINTK(PROBE, ERR, "Error in setting MWI\n"); + } + +-void +-iegbe_pci_clear_mwi(struct iegbe_hw *hw) ++void iegbe_pci_clear_mwi(struct iegbe_hw *hw) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +-#ifdef HAVE_PCI_SET_MWI +- pci_clear_mwi(adapter->pdev); +-#else +- pci_write_config_word(adapter->pdev, PCI_COMMAND, +- adapter->hw.pci_cmd_word & +- ~PCI_COMMAND_INVALIDATE); +-#endif ++ pci_clear_mwi(adapter->pdev); + } + + void + iegbe_read_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_read_config_word(adapter->pdev, reg, value); ++ pci_read_config_word(adapter->pdev, reg, value); + } + + void + iegbe_write_pci_cfg(struct iegbe_hw *hw, uint32_t reg, uint16_t *value) + { +- struct iegbe_adapter *adapter = hw->back; ++ struct iegbe_adapter *adapter = hw->back; + +- pci_write_config_word(adapter->pdev, reg, *value); ++ pci_write_config_word(adapter->pdev, reg, *value); + } + + uint32_t + iegbe_io_read(struct iegbe_hw *hw, unsigned long port) + { +- return inl(port); ++ return inl(port); + } + + void + iegbe_io_write(struct iegbe_hw *hw, unsigned long port, uint32_t value) + { +- outl(value, port); ++ outl(value, port); + } + +-#ifdef NETIF_F_HW_VLAN_TX +-static void +-iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ++static void iegbe_vlan_rx_register(struct net_device *netdev, ++ struct vlan_group *grp) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, rctl; +- +- iegbe_irq_disable(adapter); +- adapter->vlgrp = grp; +- +- if(grp) { +- /* enable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl |= E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- +- /* enable VLAN receive filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_VFE; +- rctl &= ~E1000_RCTL_CFIEN; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- iegbe_update_mng_vlan(adapter); +- } else { +- /* disable VLAN tag insert/strip */ +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- ctrl &= ~E1000_CTRL_VME; +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, rctl; + +- /* disable VLAN filtering */ +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl &= ~E1000_RCTL_VFE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { +- iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); +- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; +- } +- } ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_disable(adapter); ++ adapter->vlgrp = grp; ++ ++ if(grp) { ++ /* enable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl |= E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* enable VLAN receive filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_VFE; ++ rctl &= ~E1000_RCTL_CFIEN; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ iegbe_update_mng_vlan(adapter); ++ } else { ++ /* disable VLAN tag insert/strip */ ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ ctrl &= ~E1000_CTRL_VME; ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ ++ /* disable VLAN filtering */ ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl &= ~E1000_RCTL_VFE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { ++ iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); ++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; ++ } ++ } + +- iegbe_irq_enable(adapter); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) ++ iegbe_irq_enable(adapter); + } + +-static void +-iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t vfta, index; ++ if((adapter->hw.mng_cookie.status & ++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) { +- return; ++ return; + } +- /* add VID to filter table */ ++ /* add VID to filter table */ + index = (vid >> 0x5) & 0x7F; +- vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); ++ vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); + vfta |= (0x1 << (vid & 0x1F)); +- iegbe_write_vfta(&adapter->hw, index, vfta); ++ iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) ++static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t vfta, index; ++ u32 vfta, index; + ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_disable(adapter); +- +- if(adapter->vlgrp) { +- adapter->vlgrp->vlan_devices[vid] = NULL; +- } ++ vlan_group_set_device(adapter->vlgrp, vid, NULL); ++ if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_enable(adapter); + +- if((adapter->hw.mng_cookie.status & +- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && +- (vid == adapter->mng_vlan_id)) { +- return; +- } + /* remove VID from filter table */ +- index = (vid >> 0x5) & 0x7F; ++ index = (vid >> 0x5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); +- vfta &= ~(0x1 << (vid & 0x1F)); ++ vfta &= ~(0x1 << (vid & 0x1F)); + iegbe_write_vfta(&adapter->hw, index, vfta); + } + +-static void +-iegbe_restore_vlan(struct iegbe_adapter *adapter) ++static void iegbe_restore_vlan(struct iegbe_adapter *adapter) + { + iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); + +- if(adapter->vlgrp) { +- uint16_t vid; +- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { +- if(!adapter->vlgrp->vlan_devices[vid]) { ++ if (adapter->vlgrp) { ++ u16 vid; ++ for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { ++ if (!vlan_group_get_device(adapter->vlgrp, vid)) + continue; +- } + iegbe_vlan_rx_add_vid(adapter->netdev, vid); + } + } + } +-#endif + +-int +-iegbe_set_spd_dplx(struct iegbe_adapter *adapter, uint16_t spddplx) ++ ++int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx) + { +- adapter->hw.autoneg = 0; ++ adapter->hw.autoneg = 0x0; + +- /* Fiber NICs only allow 1000 gbps Full duplex */ +- if((adapter->hw.media_type == iegbe_media_type_fiber ++ /* Fiber NICs only allow 1000 gbps Full duplex */ ++ if((adapter->hw.media_type == iegbe_media_type_fiber + || (adapter->hw.media_type == iegbe_media_type_oem + && !iegbe_oem_phy_is_copper(&adapter->hw))) +- && spddplx != (SPEED_1000 + FULL_DUPLEX)) { +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- +- switch(spddplx) { +- case SPEED_10 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_half; +- break; +- case SPEED_10 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_10_full; +- break; +- case SPEED_100 + HALF_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_half; +- break; +- case SPEED_100 + FULL_DUPLEX: +- adapter->hw.forced_speed_duplex = iegbe_100_full; +- break; +- case SPEED_1000 + FULL_DUPLEX: ++ && spddplx != (SPEED_1000 + DUPLEX_FULL)) { ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ ++ switch(spddplx) { ++ case SPEED_10 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_10_half; ++ break; ++ case SPEED_10 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_10_full; ++ break; ++ case SPEED_100 + DUPLEX_HALF: ++ adapter->hw.forced_speed_duplex = iegbe_100_half; ++ break; ++ case SPEED_100 + DUPLEX_FULL: ++ adapter->hw.forced_speed_duplex = iegbe_100_full; ++ break; ++ case SPEED_1000 + DUPLEX_FULL: + adapter->hw.autoneg = 0x1; +- adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; +- break; +- case SPEED_1000 + HALF_DUPLEX: /* not supported */ +- default: +- DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); +- return -EINVAL; +- } +- return 0; ++ adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; ++ break; ++ case SPEED_1000 + DUPLEX_HALF: /* not supported */ ++ default: ++ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n"); ++ return -EINVAL; ++ } ++ return 0x0; + } + + static int + iegbe_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) + { +- struct pci_dev *pdev = NULL; ++ struct pci_dev *pdev = NULL; + pm_message_t state = {0x3}; + + +- switch(event) { +- case SYS_DOWN: +- case SYS_HALT: +- case SYS_POWER_OFF: +- while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { ++ switch(event) { ++ case SYS_DOWN: ++ case SYS_HALT: ++ case SYS_POWER_OFF: ++ while((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { + if(pci_dev_driver(pdev) == &iegbe_driver) { +- iegbe_suspend(pdev, state); +- } +- } ++ iegbe_suspend(pdev, state); ++ } ++ } + } +- return NOTIFY_DONE; ++ return NOTIFY_DONE; + } + + static int + iegbe_suspend(struct pci_dev *pdev, pm_message_t state) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; +- uint32_t wufc = adapter->wol; +- uint16_t cmd_word; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm; ++ uint32_t wufc = adapter->wol; ++ uint16_t cmd_word; + +- netif_device_detach(netdev); ++ netif_device_detach(netdev); + + if(netif_running(netdev)) { +- iegbe_down(adapter); ++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); ++ iegbe_down(adapter); + } +- /* +- * ICP_XXXX style MACs do not have a link up bit in +- * the STATUS register, query the PHY directly +- */ +- if(adapter->hw.mac_type != iegbe_icp_xxxx) { +- status = E1000_READ_REG(&adapter->hw, STATUS); ++ /* ++ * ICP_XXXX style MACs do not have a link up bit in ++ * the STATUS register, query the PHY directly ++ */ ++ if(adapter->hw.mac_type != iegbe_icp_xxxx) { ++ status = E1000_READ_REG(&adapter->hw, STATUS); + if(status & E1000_STATUS_LU) { +- wufc &= ~E1000_WUFC_LNKC; ++ wufc &= ~E1000_WUFC_LNKC; + } +- } else { +- int isUp = 0; ++ } else { ++ int isUp = 0x0; + if(iegbe_oem_phy_is_link_up(&adapter->hw, &isUp) != E1000_SUCCESS) { +- isUp = 0; ++ isUp = 0x0; + } + if(isUp) { +- wufc &= ~E1000_WUFC_LNKC; +- } ++ wufc &= ~E1000_WUFC_LNKC; ++ } + } + +- if(wufc) { +- iegbe_setup_rctl(adapter); +- iegbe_set_multi(netdev); +- +- /* turn on all-multi mode if wake on multicast is enabled */ +- if(adapter->wol & E1000_WUFC_MC) { +- rctl = E1000_READ_REG(&adapter->hw, RCTL); +- rctl |= E1000_RCTL_MPE; +- E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +- } ++ if(wufc) { ++ iegbe_setup_rctl(adapter); ++ iegbe_set_rx_mode(netdev); ++ ++ /* turn on all-multi mode if wake on multicast is enabled */ ++ if(adapter->wol & E1000_WUFC_MC) { ++ rctl = E1000_READ_REG(&adapter->hw, RCTL); ++ rctl |= E1000_RCTL_MPE; ++ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); ++ } + +- if(adapter->hw.mac_type >= iegbe_82540) { +- ctrl = E1000_READ_REG(&adapter->hw, CTRL); +- /* advertise wake from D3Cold */ +- #define E1000_CTRL_ADVD3WUC 0x00100000 +- /* phy power management enable */ +- ctrl |= E1000_CTRL_ADVD3WUC | +- (adapter->hw.mac_type != iegbe_icp_xxxx +- ? E1000_CTRL_EN_PHY_PWR_MGMT : 0); ++ if(adapter->hw.mac_type >= iegbe_82540) { ++ ctrl = E1000_READ_REG(&adapter->hw, CTRL); ++ /* advertise wake from D3Cold */ ++ #define E1000_CTRL_ADVD3WUC 0x00100000 ++ /* phy power management enable */ ++ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 ++ ctrl |= E1000_CTRL_ADVD3WUC | ++ (adapter->hw.mac_type != iegbe_icp_xxxx ++ ? E1000_CTRL_EN_PHY_PWR_MGMT : 0x0); + +- E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); +- } ++ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); ++ } + +- if(adapter->hw.media_type == iegbe_media_type_fiber || +- adapter->hw.media_type == iegbe_media_type_internal_serdes) { +- /* keep the laser running in D3 */ +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); +- } ++ if(adapter->hw.media_type == iegbe_media_type_fiber || ++ adapter->hw.media_type == iegbe_media_type_internal_serdes) { ++ /* keep the laser running in D3 */ ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext); ++ } + + /* Allow OEM PHYs (if any exist) to keep the laser + *running in D3 */ + iegbe_oem_fiber_live_in_suspend(&adapter->hw); + +- /* Allow time for pending master requests to run */ +- iegbe_disable_pciex_master(&adapter->hw); ++ /* Allow time for pending master requests to run */ ++ iegbe_disable_pciex_master(&adapter->hw); + +- E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); +- E1000_WRITE_REG(&adapter->hw, WUFC, wufc); ++ E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN); ++ E1000_WRITE_REG(&adapter->hw, WUFC, wufc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } else { +- E1000_WRITE_REG(&adapter->hw, WUC, 0); +- E1000_WRITE_REG(&adapter->hw, WUFC, 0); +- pci_enable_wake(pdev, 0x3, 0); +- pci_enable_wake(pdev, 0x4, 0); /* 4 == D3 cold */ +- } ++ } else { ++ E1000_WRITE_REG(&adapter->hw, WUC, 0x0); ++ E1000_WRITE_REG(&adapter->hw, WUFC, 0x0); ++ pci_enable_wake(pdev, 0x3, 0x0); ++ pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ ++ } + +- pci_save_state(pdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- if(manc & E1000_MANC_SMBUS_EN) { +- manc |= E1000_MANC_ARP_EN; +- E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ pci_save_state(pdev); ++ ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ if(manc & E1000_MANC_SMBUS_EN) { ++ manc |= E1000_MANC_ARP_EN; ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); + pci_enable_wake(pdev, 0x3, 0x1); + pci_enable_wake(pdev, 0x4, 0x1); /* 4 == D3 cold */ +- } +- } ++ } ++ } + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm & ~E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm & ~E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } + +- pci_disable_device(pdev); +- if(adapter->hw.mac_type == iegbe_icp_xxxx) { +- /* +- * ICP xxxx devices are not true PCI devices, in the context +- * of power management, disabling the bus mastership is not +- * sufficient to disable the device, it is also necessary to +- * disable IO, Memory, and Interrupts if they are enabled. +- */ +- pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); ++ pci_disable_device(pdev); ++ if(adapter->hw.mac_type == iegbe_icp_xxxx) { ++ /* ++ * ICP xxxx devices are not true PCI devices, in the context ++ * of power management, disabling the bus mastership is not ++ * sufficient to disable the device, it is also necessary to ++ * disable IO, Memory, and Interrupts if they are enabled. ++ */ ++ pci_read_config_word(pdev, PCI_COMMAND, &cmd_word); + if(cmd_word & PCI_COMMAND_IO) { +- cmd_word &= ~PCI_COMMAND_IO; ++ cmd_word &= ~PCI_COMMAND_IO; + } + if(cmd_word & PCI_COMMAND_MEMORY) { +- cmd_word &= ~PCI_COMMAND_MEMORY; ++ cmd_word &= ~PCI_COMMAND_MEMORY; + } + if(cmd_word & PCI_COMMAND_INTX_DISABLE) { +- cmd_word &= ~PCI_COMMAND_INTX_DISABLE; ++ cmd_word &= ~PCI_COMMAND_INTX_DISABLE; + } +- pci_write_config_word(pdev, PCI_COMMAND, cmd_word); +- } ++ pci_write_config_word(pdev, PCI_COMMAND, cmd_word); ++ } + +- state.event = (state.event > 0) ? 0x3 : 0; +- pci_set_power_state(pdev, state.event); +- if(gcu_suspend == 0) ++ state.event = (state.event > 0x0) ? 0x3 : 0x0; ++ pci_set_power_state(pdev, state.event); ++ if(gcu_suspend == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); +- } ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ } + gcu_iegbe_suspend(gcu, 0x3); +- gcu_suspend = 1; +- gcu_resume = 0; ++ gcu_suspend = 0x1; ++ gcu_resume = 0x0; + } +- return 0; ++ return 0x0; + } + + #ifdef CONFIG_PM + static int + iegbe_resume(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- uint32_t manc, ret_val, swsm; +- uint32_t ctrl_ext; ++ struct net_device *netdev = pci_get_drvdata(pdev); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ uint32_t manc, ret_val, swsm; ++ uint32_t ctrl_ext; + int offset; + uint32_t vdid; + +- if(gcu_resume == 0) ++ if(gcu_resume == 0x0) + { + if(gcu == NULL) { +- gcu = pci_find_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); ++ gcu = pci_get_device(PCI_VENDOR_ID_INTEL, GCU_DEVID, NULL); + pci_read_config_dword(gcu, 0x00, &vdid); +- } +- ++ } ++ + if(gcu) { + gcu_iegbe_resume(gcu); +- gcu_resume = 1; +- gcu_suspend = 0; ++ gcu_resume = 0x1; ++ gcu_suspend = 0x0; + } else { + printk("Unable to resume GCU!\n"); +- } ++ } + } + pci_set_power_state(pdev, 0x0); +- pci_restore_state(pdev); +- ret_val = pci_enable_device(pdev); +- pci_set_master(pdev); ++ pci_restore_state(pdev); ++ ret_val = pci_enable_device(pdev); ++ pci_set_master(pdev); + + pci_enable_wake(pdev, 0x3, 0x0); + pci_enable_wake(pdev, 0x4, 0x0); /* 4 == D3 cold */ + +- iegbe_reset(adapter); +- E1000_WRITE_REG(&adapter->hw, WUS, ~0); ++ iegbe_reset(adapter); ++ E1000_WRITE_REG(&adapter->hw, WUS, ~0); + offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_ST) + + PCI_ST_SMIA_OFFSET; + pci_write_config_dword(adapter->pdev, offset, 0x00000006); +@@ -5138,51 +4848,52 @@ iegbe_resume(struct pci_dev *pdev) + E1000_WRITE_REG(&adapter->hw, IMC2, ~0UL); + + if(netif_running(netdev)) { +- iegbe_up(adapter); ++ iegbe_up(adapter); + } +- netif_device_attach(netdev); +- +- if(adapter->hw.mac_type >= iegbe_82540 +- && adapter->hw.mac_type != iegbe_icp_xxxx +- && adapter->hw.media_type == iegbe_media_type_copper) { +- manc = E1000_READ_REG(&adapter->hw, MANC); +- manc &= ~(E1000_MANC_ARP_EN); +- E1000_WRITE_REG(&adapter->hw, MANC, manc); +- } ++ netif_device_attach(netdev); + +- switch(adapter->hw.mac_type) { +- case iegbe_82571: +- case iegbe_82572: +- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); +- E1000_WRITE_REG(&adapter->hw, CTRL_EXT, +- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); +- break; +- case iegbe_82573: +- swsm = E1000_READ_REG(&adapter->hw, SWSM); +- E1000_WRITE_REG(&adapter->hw, SWSM, +- swsm | E1000_SWSM_DRV_LOAD); +- break; +- default: +- break; +- } ++ if(adapter->hw.mac_type >= iegbe_82540 ++ && adapter->hw.mac_type != iegbe_icp_xxxx ++ && adapter->hw.media_type == iegbe_media_type_copper) { ++ manc = E1000_READ_REG(&adapter->hw, MANC); ++ manc &= ~(E1000_MANC_ARP_EN); ++ E1000_WRITE_REG(&adapter->hw, MANC, manc); ++ } ++ ++ switch(adapter->hw.mac_type) { ++ case iegbe_82571: ++ case iegbe_82572: ++ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ++ E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ++ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); ++ break; ++ case iegbe_82573: ++ swsm = E1000_READ_REG(&adapter->hw, SWSM); ++ E1000_WRITE_REG(&adapter->hw, SWSM, ++ swsm | E1000_SWSM_DRV_LOAD); ++ break; ++ default: ++ break; ++ } ++#endif + +- return 0; ++ return 0x0; + } +-#endif ++ + #ifdef CONFIG_NET_POLL_CONTROLLER + /* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +-static void +-iegbe_netpoll(struct net_device *netdev) ++static void iegbe_netpoll(struct net_device *netdev) + { +- struct iegbe_adapter *adapter = netdev_priv(netdev); +- disable_irq(adapter->pdev->irq); +- iegbe_intr(adapter->pdev->irq, netdev, NULL); +- enable_irq(adapter->pdev->irq); ++ struct iegbe_adapter *adapter = netdev_priv(netdev); ++ disable_irq(adapter->pdev->irq); ++ iegbe_intr(adapter->pdev->irq, netdev); ++ enable_irq(adapter->pdev->irq); + } + #endif + ++ + /* iegbe_main.c */ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- This program is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ This program is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *****************************************************************************/ + /************************************************************************** +@@ -65,11 +65,6 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + +-/* Define specific BCM functions */ +-static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); +-static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); +-static int32_t oi_phy_setup (struct iegbe_hw *hw); +- + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -84,7 +79,7 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + { + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * see iegbe_setup_copper_link() as the primary example. Look at both + * the M88 and IGP functions that are called for ideas, possibly for + * power management. +@@ -102,14 +97,14 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + /* AFU: add test to exit out if improper phy type + */ +- /* relevent parts of iegbe_copper_link_preconfig */ +- ctrl = E1000_READ_REG(hw, CTRL); +- ctrl |= E1000_CTRL_SLU; +- ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); +- E1000_WRITE_REG(hw, CTRL, ctrl); +- ++ /* relevent parts of iegbe_copper_link_preconfig */ ++ ctrl = E1000_READ_REG(hw, CTRL); ++ ctrl |= E1000_CTRL_SLU; ++ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ++ E1000_WRITE_REG(hw, CTRL, ctrl); ++ + /* this is required for *hw init */ +- ret_val = iegbe_oem_detect_phy(hw); ++ ret_val = iegbe_oem_detect_phy(hw); + if(ret_val) { + return ret_val; + } +@@ -119,23 +114,13 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- return E1000_SUCCESS; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +- if(ret_val) { +- return ret_val; +- } +- break; +- case BCM5481_PHY_ID: +- ret_val = iegbe_oem_link_bcm5481_setup(hw); +- if(ret_val) { +- return ret_val; ++ if(ret_val) { ++ return ret_val; + } +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -143,16 +128,16 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + + if(hw->autoneg) { + ret_val = iegbe_copper_link_autoneg(hw); +- if(ret_val) { +- return ret_val; +- } ++ if(ret_val) { ++ return ret_val; + } ++ } + else { + DEBUGOUT("Forcing speed and duplex\n"); + ret_val = iegbe_phy_force_speed_duplex(hw); + } +- +- /* ++ ++ /* + * Check link status. Wait up to 100 microseconds for link to become + * valid. + */ +@@ -194,51 +179,6 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +-/** +- * iegbe_oem_link_bcm5481_setup +- * @hw: iegbe_hw struct containing device specific information +- * +- * Returns E1000_SUCCESS, negative E1000 error code on failure +- * +- * copied verbatim from iegbe_oem_link_m88_setup +- **/ +-static int32_t +-iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) +-{ +- int32_t ret_val; +- uint16_t phy_data; +- +- //DEBUGFUNC(__func__); +- +- if(!hw) +- return -1; +- +- /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ +- if(hw->phy_reset_disable) +- return E1000_SUCCESS; +- +- // Enable MDIX in extended control reg. +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- phy_data &= ~BCM5481_ECTRL_DISMDIX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); +- return ret_val; +- } +- +- ret_val = oi_phy_setup (hw); +- if (ret_val) +- return ret_val; +- +- return E1000_SUCCESS; +-} + + /** + * iegbe_oem_link_m88_setup +@@ -253,7 +193,7 @@ static int32_t + iegbe_oem_link_m88_setup(struct iegbe_hw *hw) + { + int32_t ret_val; +- uint16_t phy_data; ++ uint16_t phy_data = 0; + + DEBUGFUNC1("%s",__func__); + +@@ -261,7 +201,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + return -1; + } + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + phy_data |= 0x00000008; + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); +@@ -279,7 +219,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; + +- /* ++ /* + * Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds +@@ -305,7 +245,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + break; + } + +- /* ++ /* + * Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity +@@ -316,25 +256,25 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + + if(hw->disable_polarity_correction == 1) { + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; +- } ++ } + ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } + +- /* ++ /* + * For Truxton, it is necessary to add RGMII tx and rx + * timing delay though the EXT_PHY_SPEC_CTRL register + */ +@@ -350,13 +290,13 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + } +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + + /* SW Reset the PHY so all changes take effect */ + ret_val = iegbe_phy_hw_reset(hw); +@@ -371,7 +311,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + /** + * iegbe_oem_force_mdi + * @hw: iegbe_hw struct containing device specific information +- * @resetPhy: returns true if after calling this function the ++ * @resetPhy: returns true if after calling this function the + * PHY requires a reset + * + * Returns E1000_SUCCESS, negative E1000 error code on failure +@@ -379,7 +319,7 @@ iegbe_oem_link_m88_setup(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_force_mdi(struct iegbe_hw *hw, int *resetPhy) + { + #ifdef EXTERNAL_MDIO +@@ -393,35 +333,30 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + return -1; + } + +- /* ++ /* + * a boolean to indicate if the phy needs to be reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; + } +- ++ + /* +- * Clear Auto-Crossover to force MDI manually. M88E1000 requires ++ * Clear Auto-Crossover to force MDI manually. M88E1000 requires + * MDI forced whenever speed are duplex are forced. + */ +- ++ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); +@@ -458,7 +393,7 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_phy_reset_dsp(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -478,10 +413,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * no-op. + */ + switch (hw->phy_id) { +- case M88E1000_I_PHY_ID: +- case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: ++ case M88E1000_I_PHY_ID: ++ case M88E1141_E_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -508,7 +441,7 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + * This is called from iegbe_phy_force_speed_duplex, which is + * called from iegbe_oem_setup_link. + **/ +-int32_t ++int32_t + iegbe_oem_cleanup_after_phy_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -520,29 +453,24 @@ iegbe_oem_cleanup_after_phy_reset(struct + + if(!hw) { + return -1; +- } ++ } + +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +- * Because we reset the PHY above, we need to re-force ++ * Because we reset the PHY above, we need to re-force + * TX_CLK in the Extended PHY Specific Control Register to + * 25MHz clock. This value defaults back to a 2.5MHz clock + * when the PHY is reset. + */ + + ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_EXT_SPEC_CTRL register\n"); +@@ -550,22 +478,23 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data |= M88E1000_EPSCR_TX_CLK_25; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_EXT_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { +- DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL register\n"); ++ DEBUGOUT("Unable to write M88E1000_EXT_PHY_SPEC_CTRL " ++ "register\n"); + return ret_val; + } + + /* + * In addition, because of the s/w reset above, we need to enable +- * CRX on TX. This must be set for both full and half duplex ++ * CRX on TX. This must be set for both full and half duplex + * operation. + */ + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read M88E1000_PHY_SPEC_CTRL register\n"); +@@ -573,12 +502,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + } + + phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX; +- ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if(ret_val) { + DEBUGOUT("Unable to write M88E1000_PHY_SPEC_CTRL register\n"); + return ret_val; +- } ++ } + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -604,12 +533,12 @@ iegbe_oem_cleanup_after_phy_reset(struct + * This is called from iegbe_oem_setup_link which is + * called from iegbe_setup_link. + **/ +-static int32_t ++static int32_t + iegbe_oem_set_phy_mode(struct iegbe_hw *hw) + { + /* + * it is unclear if it is necessary to set the phy mode. Right now only +- * one MAC 82545 Rev 3 does it, but the other MACs like Tolapai do not. ++ * one MAC 82545 Rev 3 does it, but the other MACs like tola do not. + * Leave the functionality off for now until it is determined that Tolapai + * needs it as well. + */ +@@ -638,41 +567,37 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + #ifndef skip_set_mode + DEBUGOUT("No need to call oem_set_phy_mode on Truxton\n"); + #else +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton. + * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_read_eeprom(hw, +- EEPROM_PHY_CLASS_WORD, +- 1, ++ ret_val = iegbe_read_eeprom(hw, ++ EEPROM_PHY_CLASS_WORD, ++ 1, + &eeprom_data); + if(ret_val) { + return ret_val; + } + +- if((eeprom_data != EEPROM_RESERVED_WORD) && +- (eeprom_data & EEPROM_PHY_CLASS_A)) ++ if((eeprom_data != EEPROM_RESERVED_WORD) && ++ (eeprom_data & EEPROM_PHY_CLASS_A)) + { +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_PAGE_SELECT, +- 0x000B); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_PAGE_SELECT, ++ 0x000B); + if(ret_val) { +- DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT register on PHY\n"); ++ DEBUGOUT("Unable to write to M88E1000_PHY_PAGE_SELECT " ++ "register on PHY\n"); + return ret_val; + } + +- ret_val = iegbe_oem_write_phy_reg_ex(hw, +- M88E1000_PHY_GEN_CONTROL, +- 0x8104); ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, ++ M88E1000_PHY_GEN_CONTROL, ++ 0x8104); + if(ret_val) { + DEBUGOUT("Unable to write to M88E1000_PHY_GEN_CONTROL" + "register on PHY\n"); +@@ -687,11 +612,12 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + return -E1000_ERR_PHY_TYPE; + } + #endif +- ++ + return E1000_SUCCESS; + + } + ++ + /** + * iegbe_oem_detect_phy + * @hw: iegbe_hw struct containing device specific information +@@ -702,7 +628,7 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * + * This borrows heavily from iegbe_detect_gig_phy + **/ +-static int32_t ++static int32_t + iegbe_oem_detect_phy(struct iegbe_hw *hw) + { + int32_t ret_val; +@@ -715,33 +641,20 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + +-{ +- // If MAC2 (BCM5395 switch), manually detect the phy +- struct iegbe_adapter *adapter; +- uint32_t device_number; +- adapter = (struct iegbe_adapter *) hw->back; +- device_number = PCI_SLOT(adapter->pdev->devfn); +- if (device_number == ICP_XXXX_MAC_2) { +- hw->phy_id = BCM5395S_PHY_ID; +- hw->phy_revision = 0; +- return E1000_SUCCESS; +- } +-} +- +- + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); + return ret_val; + } +- ++ + usec_delay(0x14); + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID2, &phy_id_low); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID2\n"); + return ret_val; + } +- hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + phy_id_low); ++ hw->phy_id = (uint32_t) ((phy_id_high << 0x10) + ++ (phy_id_low & PHY_REVISION_MASK)); + hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; + + return E1000_SUCCESS; +@@ -753,15 +666,15 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + * @hw: iegbe_hw struct containing device specific information + * + * Returns the value of the Inter Packet Gap (IPG) Transmit Time (IPGT) in the +- * Transmit IPG register appropriate for the given PHY. This field is only 10 ++ * Transmit IPG register appropriate for the given PHY. This field is only 10 + * bits wide. + * + * In the original iegbe code, only the IPGT field varied between media types. +- * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would ++ * If the OEM phy requires setting IPG Receive Time 1 & 2 Registers, it would + * be required to modify the iegbe_config_tx() function to accomdate the change + * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_tipg(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -777,15 +690,13 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return DEFAULT_ICP_XXXX_TIPG_IPGT; + } +- ++ + return phy_num; + + #else /* ifdef EXTERNAL_MDIO */ +@@ -803,15 +714,15 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + * iegbe_oem_phy_is_copper + * @hw: iegbe_hw struct containing device specific information + * +- * Test for media type within the iegbe driver is common, so this is a simple +- * test for copper PHYs. The ICP_XXXX family of controllers initially only +- * supported copper interconnects (no TBI (ten bit interface) for Fiber +- * existed). If future revs support either Fiber or an internal SERDES, it +- * may become necessary to evaluate where this function is used to go beyond ++ * Test for media type within the iegbe driver is common, so this is a simple ++ * test for copper PHYs. The ICP_XXXX family of controllers initially only ++ * supported copper interconnects (no TBI (ten bit interface) for Fiber ++ * existed). If future revs support either Fiber or an internal SERDES, it ++ * may become necessary to evaluate where this function is used to go beyond + * determining whether or not media type is just copper. + * + **/ +-int ++int + iegbe_oem_phy_is_copper(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -827,23 +738,21 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; + } +- ++ + return isCopper; + + #else /* ifdef EXTERNAL_MDIO */ + +- /* ++ /* + * caught between returning true or false. True allows it to + * be entered into && statements w/o ill effect, but false +- * would make more sense ++ * would make more sense + */ + DEBUGOUT("Invalid value for transceiver type, return FALSE\n"); + return FALSE; +@@ -856,19 +765,19 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + * iegbe_oem_get_phy_dev_number + * @hw: iegbe_hw struct containing device specific information + * +- * For ICP_XXXX family of devices, there are 3 MACs, each of which may +- * have a different PHY (and indeed a different media interface). This +- * function is used to indicate which of the MAC/PHY pairs we are interested ++ * For ICP_XXXX family of devices, there are 3 MACs, each of which may ++ * have a different PHY (and indeed a different media interface). This ++ * function is used to indicate which of the MAC/PHY pairs we are interested + * in. +- * ++ * + **/ +-uint32_t ++uint32_t + iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO + +- /* +- * for ICP_XXXX family of devices, the three network interfaces are ++ /* ++ * for ICP_XXXX family of devices, the three network interfaces are + * differentiated by their PCI device number, where the three share + * the same PCI bus + */ +@@ -886,15 +795,15 @@ iegbe_oem_get_phy_dev_number(struct iegb + + switch(device_number) + { +- case ICP_XXXX_MAC_0: ++ case ICP_XXXX_MAC_0: ++ hw->phy_addr = 0x00; ++ break; ++ case ICP_XXXX_MAC_1: + hw->phy_addr = 0x01; + break; +- case ICP_XXXX_MAC_1: ++ case ICP_XXXX_MAC_2: + hw->phy_addr = 0x02; + break; +- case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x00; +- break; + default: hw->phy_addr = 0x00; + } + return hw->phy_addr; +@@ -915,7 +824,7 @@ iegbe_oem_get_phy_dev_number(struct iegb + * @cmd: the original IOCTL command that instigated the call chain. + * + * This function abstracts out the code necessary to service the +- * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. ++ * SIOCSMIIREG case within the iegbe_mii_ioctl() for oem PHYs. + * iegbe_mii_ioctl() was implemented for copper phy's only and this + * function will only be called if iegbe_oem_phy_is_copper() returns true for + * a given MAC. Note that iegbe_mii_ioctl() has a compile flag +@@ -924,14 +833,14 @@ iegbe_oem_get_phy_dev_number(struct iegb + * NOTE: a spinlock is in effect for the duration of this call. It is + * imperative that a negative value be returned on any error, so + * the spinlock can be released properly. +- * ++ * + **/ + int + iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd) + { + #ifdef EXTERNAL_MDIO +- ++ + struct mii_ioctl_data *data = if_mii(ifr); + uint16_t mii_reg = data->val_in; + uint16_t spddplx; +@@ -942,12 +851,6 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } +- +- // If MAC2 (BCM5395 switch) then leave now +- if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { +- return -1; +- } +- + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -956,7 +859,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(mii_reg & MII_CR_AUTO_NEG_EN) { + adapter->hw.autoneg = 1; + adapter->hw.autoneg_advertised = ICP_XXXX_AUTONEG_ADV_DEFAULT; +- } ++ } + else { + if(mii_reg & 0x40) { + spddplx = SPEED_1000; +@@ -976,7 +879,7 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(netif_running(adapter->netdev)) { + iegbe_down(adapter); + iegbe_up(adapter); +- } ++ } + else { + iegbe_reset(adapter); + } +@@ -1043,10 +946,10 @@ void iegbe_oem_fiber_live_in_suspend(str + * Note: The call to iegbe_get_regs() assumed an array of 24 elements + * where the last 11 are passed to this function. If the array + * that is passed to the calling function has its size or element +- * defintions changed, this function becomes broken. ++ * defintions changed, this function becomes broken. + * + **/ +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_len) + { + #define EXPECTED_ARRAY_LEN 11 +@@ -1062,13 +965,13 @@ void iegbe_oem_get_phy_regs(struct iegbe + * Use the corrected_length variable to make sure we don't exceed that + * length + */ +- corrected_len = data_len>EXPECTED_ARRAY_LEN ++ corrected_len = data_len>EXPECTED_ARRAY_LEN + ? EXPECTED_ARRAY_LEN : data_len; + memset(data, 0, corrected_len*sizeof(uint32_t)); + + #ifdef EXTERNAL_MDIO + +- /* ++ /* + * Fill data[] with... + * + * [0] = cable length +@@ -1084,16 +987,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, +- M88E1000_PHY_SPEC_STATUS, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, ++ M88E1000_PHY_SPEC_STATUS, + (uint16_t *) &data[0]); + } + if(corrected_len > 0x1){ +@@ -1106,7 +1004,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + data[0x3] = 0x0; /* Dummy (to align w/ IGP phy reg dump) */ + } + if(corrected_len > 0x4) { +- iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, ++ iegbe_oem_read_phy_reg_ex(&adapter->hw, M88E1000_PHY_SPEC_CTRL, + (uint16_t *) &data[0x4]); + } + if(corrected_len > 0x5) { +@@ -1144,7 +1042,7 @@ void iegbe_oem_get_phy_regs(struct iegbe + * This is called from iegbe_set_phy_loopback in response from call from + * ethtool to place the PHY into loopback mode. + **/ +-int ++int + iegbe_oem_phy_loopback(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO +@@ -1165,23 +1063,18 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * was that nonintegrated called iegbe_phy_reset_clk_and_crs(), + * hopefully this won't matter as CRS required for half-duplex + * operation and this is set to full duplex. +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + + /* turn off Auto-MDI/MDIX */ +- /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, ++ /*ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, + M88E1000_PHY_SPEC_CTRL, 0x0808); + if(ret_val) + { +@@ -1206,10 +1099,10 @@ iegbe_oem_phy_loopback(struct iegbe_adap + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return ret_val; + } +- +- ++ ++ + /* force 1000, set loopback */ +- /*ret_val = ++ /*ret_val = + iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x4140); */ + ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, 0x6100); + if(ret_val) { +@@ -1228,21 +1121,21 @@ iegbe_oem_phy_loopback(struct iegbe_adap + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg); + + /* +- * Write out to PHY registers 29 and 30 to disable the Receiver. ++ * Write out to PHY registers 29 and 30 to disable the Receiver. + * This directly lifted from iegbe_phy_disable_receiver(). +- * ++ * + * The code is currently commented out as for the M88 used in + * Truxton, registers 29 and 30 are unutilized. Leave in, just +- * in case we are on the receiving end of an 'undocumented' ++ * in case we are on the receiving end of an 'undocumented' + * feature + */ +- /* ++ /* + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001F); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FFC); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 29, 0x001A); + * iegbe_oem_write_phy_reg_ex(&adapter->hw, 30, 0x8FF0); + */ +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1268,15 +1161,15 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * ethtool to place the PHY out of loopback mode. This handles the OEM + * specific part of loopback cleanup. + **/ +-void ++void + iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter) + { + #ifdef EXTERNAL_MDIO + +- /* +- * This borrows liberally from iegbe_loopback_cleanup(). ++ /* ++ * This borrows liberally from iegbe_loopback_cleanup(). + * making note that the M88 phy is what'll be used on Truxton +- * ++ * + * Loopback cleanup is the same for all supported PHYs. + */ + int32_t ret_val; +@@ -1289,38 +1182,32 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); +- return; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; +- +- ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(&adapter->hw, PHY_CTRL, + &phy_reg); + if(ret_val) { + DEBUGOUT("Unable to read to register PHY_CTRL\n"); + return; + } +- ++ + if(phy_reg & MII_CR_LOOPBACK) { + phy_reg &= ~MII_CR_LOOPBACK; +- +- ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, ++ ++ ret_val = iegbe_oem_write_phy_reg_ex(&adapter->hw, PHY_CTRL, + phy_reg); + if(ret_val) { + DEBUGOUT("Unable to write to register PHY_CTRL\n"); + return; + } +- ++ + iegbe_phy_reset(&adapter->hw); + } + } +- ++ + #endif /* ifdef EXTERNAL_MDIO */ + return; + +@@ -1336,7 +1223,7 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-uint32_t ++uint32_t + iegbe_oem_phy_speed_downgraded(struct iegbe_hw *hw, uint16_t *isDowngraded) + { + #ifdef EXTERNAL_MDIO +@@ -1356,24 +1243,19 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *isDowngraded = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } +- +- *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) ++ ++ *isDowngraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) + >> M88E1000_PSSR_DOWNSHIFT_SHIFT; +- +- break; ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return 1; +@@ -1388,7 +1270,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + } + + *isDowngraded = 0; +- return 0; ++ return 0; + + #endif /* ifdef EXTERNAL_MDIO */ + } +@@ -1403,7 +1285,7 @@ iegbe_oem_phy_speed_downgraded(struct ie + * Called by iegbe_check_downshift(), checks the PHY to see if it running + * at as speed slower than its maximum. + **/ +-int32_t ++int32_t + iegbe_oem_check_polarity(struct iegbe_hw *hw, uint16_t *polarity) + { + #ifdef EXTERNAL_MDIO +@@ -1417,33 +1299,27 @@ iegbe_oem_check_polarity(struct iegbe_hw + return -1; + } + +- /* ++ /* + * borrow liberally from iegbe_check_polarity. + * Make note that the M88 phy is what'll be used on Truxton + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *polarity = 0; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +- ret_val = iegbe_oem_read_phy_reg_ex(hw, +- M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; + } + +- *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) ++ *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) + >> M88E1000_PSSR_REV_POLARITY_SHIFT; +- +- break; +- ++ ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -1472,7 +1348,7 @@ iegbe_oem_check_polarity(struct iegbe_hw + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_full_duplex(struct iegbe_hw *hw, int *isFD) + { + #ifdef EXTERNAL_MDIO +@@ -1485,40 +1361,22 @@ iegbe_oem_phy_is_full_duplex(struct iegb + if(!hw || !isFD) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ +- ++ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always full duplex */ +- *isFD = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_100BTXFD: +- *isFD = 1; +- break; +- default: +- *isFD = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; +- } ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); ++ if(ret_val) { ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; ++ } + *isFD = (phy_data & M88E1000_PSSR_DPLX) != 0; +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1546,7 +1404,7 @@ iegbe_oem_phy_is_full_duplex(struct iegb + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_speed_1000(struct iegbe_hw *hw, int *is1000) + { + #ifdef EXTERNAL_MDIO +@@ -1565,28 +1423,10 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000mb */ +- *is1000 = 1; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_1KBTFD: +- case BCM5481_ASTAT_1KBTHD: +- *is1000 = 1; +- break; +- default: +- *is1000 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); + return ret_val; +@@ -1638,28 +1478,9 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Always 1000Mb, never 100mb */ +- *is100 = 0; +- break; +- +- case BCM5481_PHY_ID: +- ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); +- if(ret_val) return ret_val; +- +- switch (BCM5481_ASTAT_HCD(phy_data)) { +- case BCM5481_ASTAT_100BTXFD: +- case BCM5481_ASTAT_100BTXHD: +- *is100 = 1; +- break; +- default: +- *is100 = 0; +- } +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -1714,29 +1535,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- /* The downshift status is checked only once, after link is +- * established and it stored in the hw->speed_downgraded parameter.*/ ++ /* The downshift status is checked only once, after link is ++ * established and it stored in the hw->speed_downgraded parameter.*/ + phy_info->downshift = (iegbe_downshift)hw->speed_downgraded; +- +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, ++ ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_CTRL\n"); + return ret_val; + } + +- phy_info->extended_10bt_distance = +- (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) ++ phy_info->extended_10bt_distance = ++ (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) + >> M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; + phy_info->polarity_correction = +- (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) ++ (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) + >> M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; + + /* Check polarity status */ +@@ -1747,11 +1563,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + + phy_info->cable_polarity = polarity; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +- DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); +- return ret_val; ++ DEBUGOUT("Unable to read register M88E1000_PHY_SPEC_STATUS\n"); ++ return ret_val; + } + + phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) +@@ -1761,24 +1577,24 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + /* Cable Length Estimation and Local/Remote Receiver Information + * are only valid at 1000 Mbps. + */ +- phy_info->cable_length = ++ phy_info->cable_length = + (phy_data & M88E1000_PSSR_CABLE_LENGTH) + >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; + +- ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_1000T_STATUS, + &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_1000T_STATUS\n"); + return ret_val; + } + +- phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ++ phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) + >> SR_1000T_LOCAL_RX_STATUS_SHIFT; +- +- phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ++ ++ phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) + >> SR_1000T_REMOTE_RX_STATUS_SHIFT; + } +- ++ + break; + default: + DEBUGOUT("Invalid PHY ID\n"); +@@ -1801,7 +1617,7 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * This function will perform a software initiated reset of + * the PHY + **/ +-int32_t ++int32_t + iegbe_oem_phy_hw_reset(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1815,18 +1631,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + return -1; + } + /* +- * This code pretty much copies the default case from ++ * This code pretty much copies the default case from + * iegbe_phy_reset() as that is what is appropriate for +- * the M88 used in truxton. ++ * the M88 used in truxton. + */ + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1864,7 +1675,7 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * to perform and post reset initialiation. Not all PHYs require + * this, which is why it was split off as a seperate function. + **/ +-void ++void + iegbe_oem_phy_init_script(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1877,19 +1688,17 @@ iegbe_oem_phy_init_script(struct iegbe_h + + /* call the GCU func that can do any phy specific init + * functions after a reset +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton + * +- * The closest thing is in iegbe_phy_init_script, however this is ++ * The closest thing is in iegbe_phy_init_script, however this is + * for the IGP style of phy. This is probably a no-op for truxton + * but may be needed by OEM's later on +- * ++ * + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1926,13 +1735,8 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + +- if (hw->phy_id == BCM5395S_PHY_ID) { +- DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); +- return -1; +- } +- + /* call the GCU func that will read the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_read_phy_reg_ex. +@@ -1940,7 +1744,7 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * NOTE: this is 1 (of 2) functions that is truly dependant on the + * gcu module + */ +- ++ + ret_val = gcu_read_eth_phy(iegbe_oem_get_phy_dev_number(hw), + reg_addr, phy_data); + if(ret_val) { +@@ -1962,10 +1766,10 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + * + * Returns E1000_SUCCESS, negative E1000 error code on failure + * +- * This is called from iegbe_config_mac_to_phy. Various supported ++ * This is called from iegbe_config_mac_to_phy. Various supported + * Phys may require the RGMII/RMII Translation gasket be set to RMII. + **/ +-int32_t ++int32_t + iegbe_oem_set_trans_gasket(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -1978,17 +1782,12 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ + break; + /* Add your PHY_ID here if your device requires an RMII interface +- case YOUR_PHY_ID: ++ case YOUR_PHY_ID: + ctrl_aux_reg = E1000_READ_REG(hw, CTRL_AUX); + ctrl_aux_reg |= E1000_CTRL_AUX_ICP_xxxx_MII_TGS; // Set the RGMII_RMII bit + */ +@@ -2032,7 +1831,7 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + return -1; + } + /* call the GCU func that will write to the phy +- * ++ * + * Make note that the M88 phy is what'll be used on Truxton. + * + * The closest thing is in iegbe_write_phy_reg_ex +@@ -2062,11 +1861,11 @@ iegbe_oem_write_phy_reg_ex(struct iegbe_ + * @hw struct iegbe_hw hardware specific data + * + * iegbe_reset_hw is called to reset the MAC. If, for +- * some reason the PHY needs to be reset as well, this ++ * some reason the PHY needs to be reset as well, this + * should return TRUE and then iegbe_oem_phy_hw_reset() + * will be called. + **/ +-int ++int + iegbe_oem_phy_needs_reset_with_mac(struct iegbe_hw *hw) + { + #ifdef EXTERNAL_MDIO +@@ -2079,16 +1878,14 @@ iegbe_oem_phy_needs_reset_with_mac(struc + return FALSE; + } + +- /* ++ /* + * From the original iegbe driver, the M88 +- * PHYs did not seem to need this reset, ++ * PHYs did not seem to need this reset, + * so returning FALSE. + */ + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -2116,7 +1913,7 @@ iegbe_oem_phy_needs_reset_with_mac(struc + * tweaking of the PHY, for PHYs that support a DSP. + * + **/ +-int32_t ++int32_t + iegbe_oem_config_dsp_after_link_change(struct iegbe_hw *hw, + int link_up) + { +@@ -2138,8 +1935,6 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- case BCM5481_PHY_ID: +- case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -2165,7 +1960,7 @@ iegbe_oem_config_dsp_after_link_change(s + * + * + **/ +-int32_t ++int32_t + iegbe_oem_get_cable_length(struct iegbe_hw *hw, + uint16_t *min_length, + uint16_t *max_length) +@@ -2177,21 +1972,15 @@ iegbe_oem_get_cable_length(struct iegbe_ + uint16_t phy_data; + + DEBUGFUNC1("%s",__func__); +- ++ + if(!hw || !min_length || !max_length) { + return -1; + } + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- case BCM5481_PHY_ID: +- *min_length = 0; +- *max_length = iegbe_igp_cable_length_150; +- break; +- + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- ret_val = iegbe_oem_read_phy_reg_ex(hw, ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, + M88E1000_PHY_SPEC_STATUS, + &phy_data); + if(ret_val) { +@@ -2246,13 +2035,13 @@ iegbe_oem_get_cable_length(struct iegbe_ + /** + * iegbe_oem_phy_is_link_up + * @hw iegbe_hw struct containing device specific information +- * @isUp a boolean returning true if link is up ++ * @isUp a boolean returning true if link is up + * + * This is called as part of iegbe_config_mac_to_phy() to align + * the MAC with the PHY. It turns out on ICP_XXXX, this is not + * done automagically. + **/ +-int32_t ++int32_t + iegbe_oem_phy_is_link_up(struct iegbe_hw *hw, int *isUp) + { + #ifdef EXTERNAL_MDIO +@@ -2266,35 +2055,19 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + if(!hw || !isUp) { + return -1; + } +- /* ++ /* + * Make note that the M88 phy is what'll be used on Truxton + * see iegbe_config_mac_to_phy + */ + + switch (hw->phy_id) { +- case BCM5395S_PHY_ID: +- /* Link always up */ +- *isUp = TRUE; +- return E1000_SUCCESS; +- break; +- +- case BCM5481_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); +- if(ret_val) +- { +- DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); +- return ret_val; +- } +- statusMask = BCM5481_ESTAT_LINK; +- break; +- +- case M88E1000_I_PHY_ID: ++ case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: +- iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +- ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, ++ &phy_data); + statusMask = M88E1000_PSSR_LINK; +- break; ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -2319,213 +2092,3 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + +- +- +-//----- +-// Read BCM5481 expansion register +-// +-int32_t +-bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) +-{ +- int ret; +- uint16_t selector; +- uint16_t reg_data; +- +- // Get the current value of bits 15:12 +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); +- if (ret) +- return ret; +- +- // Select the expansion register +- selector &= 0xf000; +- selector |= (0xf << 8) | (reg); +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- // Read the expansion register +- ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); +- +- // De-select the expansion registers. +- selector &= 0xf000; +- iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); +- +- if (ret) +- return ret; +- +- *data = reg_data; +- return ret; +-} +- +-//----- +-// Read reg 0x18 sub-register +-// +-static int32_t +-bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x18, sv +- tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x18, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read reg 0x1C sub-register +-// +-int32_t +-bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) +-{ +- int ret; +- uint16_t tmp_data; +- +- // Select reg 0x1c, sv +- tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); +- if(ret) +- return ret; +- +- // Read reg 0x1c, sv +- ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); +- if(ret) +- return ret; +- +- *data = tmp_data; +- return ret; +-} +- +-//----- +-// Read-modify-write a 0x1C register. +-// +-// hw - hardware access info. +-// reg - 0x1C register to modify. +-// data - bits which should be set. +-// mask - the '1' bits in this argument will be cleared in the data +-// read from 'reg' then 'data' will be or'd in and the result +-// will be written to 'reg'. +- +-int32_t +-bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) +-{ +- int32_t ret; +- uint16_t reg_data; +- +- ret = 0; +- +- ret = bcm5481_read_1csv (hw, reg, ®_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); +- return ret; +- } +- +- reg_data &= ~mask; +- reg_data |= (BCM5481_R1CH_WE | data); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481 1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); +- return ret; +- } +- +- return ret; +-} +- +-int32_t +-oi_phy_setup (struct iegbe_hw *hw) +-{ +- int ret; +- uint16_t pmii_data; +- uint16_t mctrl_data; +- uint16_t cacr_data; +- uint16_t sc1_data; +- uint16_t lctl_data; +- +- ret = 0; +- +- // Set low power mode via reg 0x18, sv010, bit 6 +- // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. +- ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); +- return ret; +- } +- +- // Set the LPM bit in the data just read and write back to sv010 +- // The shadow register select bits [2:0] are set by reading the sv010 +- // register. +- pmii_data |= BCM5481_R18H_SV010_LPM; +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 +- +- if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) +- { +- DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); +- return ret; +- } +- mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R18H register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); +- return ret; +- } +- +- +- // Enable RGMII transmit clock delay in reg 0x1c, sv00011 +- ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); +- if (ret) +- { +- DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); +- printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); +- return ret; +- } +- +- cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); +- +- ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); +- if(ret) +- { +- DEBUGOUT("Unable to write BCM5481_R1CH register\n"); +- printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); +- return ret; +- } +- +- // Enable dual link speed indication (0x1c, sv 00010, bit 2) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); +- if (ret) +- return ret; +- +- // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) +- ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); +- if (ret) +- return ret; +- +- return ret; +-} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -2,31 +2,31 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + +- This program is free software; you can redistribute it and/or modify ++ This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + +- This program is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ This program is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- The full GNU General Public License is included in this distribution ++ The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: +- +- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 + + *******************************************************************************/ + #ifndef _IEGBE_OEM_PHY_H_ +@@ -45,10 +45,10 @@ int32_t iegbe_oem_set_trans_gasket(struc + uint32_t iegbe_oem_get_tipg(struct iegbe_hw *hw); + int iegbe_oem_phy_is_copper(struct iegbe_hw *hw); + uint32_t iegbe_oem_get_phy_dev_number(struct iegbe_hw *hw); +-int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, ++int iegbe_oem_mii_ioctl(struct iegbe_adapter *adapter, unsigned long flags, + struct ifreq *ifr, int cmd); + void iegbe_oem_fiber_live_in_suspend(struct iegbe_hw *hw); +-void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, ++void iegbe_oem_get_phy_regs(struct iegbe_adapter *adapter, uint32_t *data, + uint32_t data_length); + int iegbe_oem_phy_loopback(struct iegbe_adapter *adapter); + void iegbe_oem_loopback_cleanup(struct iegbe_adapter *adapter); +@@ -94,81 +94,14 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_MAC_2 2 + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ +-#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL +-#define BCM5481_PHY_ID 0x0143BCA2 +-#define BCM5395S_PHY_ID 0x0143BCF0 ++#define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +- #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F ++ #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x0F + #else + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + +-//----- +-// BCM5481 specifics +- +-#define BCM5481_ECTRL (0x10) +-#define BCM5481_ESTAT (0x11) +-#define BCM5481_RXERR (0x12) +-#define BCM5481_EXPRW (0x15) +-#define BCM5481_EXPACC (0x17) +-#define BCM5481_ASTAT (0x19) +-#define BCM5481_R18H (0x18) +-#define BCM5481_R1CH (0x1c) +- +-//----- +-// indirect register access via register 18h +- +-#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. +-#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control +-#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T +-#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control +-#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test +-#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control +- +-#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity +-#define BCM5481_R18H_SV010_LPM (1 << 6) +-#define BCM5481_R18H_SV111_SKEW (1 << 8) +-#define BCM5481_R18H_WE (1 << 15) // Write enable +- +-// 0x1c registers +-#define BCM5481_R1CH_SV_SHIFT (10) +-#define BCM5481_R1CH_SV_MASK (0x1f) +-#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 +-#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control +-#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control +-#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 +- +-// 0x1c common +-#define BCM5481_R1CH_WE (1 << 15) // Write enable +- +-// 0x1c, sv 00010 +-#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed +- +-// 0x1c, sv 00011 +-#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay +- +-// 0x1c, sv 01001 +-#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED +-#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED +- +- +-#define BCM5481_ECTRL_DISMDIX (1 <<14) +- +-#define BCM5481_MCTRL_AUTOMDIX (1 <<9) +- +-#define BCM5481_ESTAT_LINK (1 << 8) +- +-#define BCM5481_ASTAT_ANC (1 << 15) +-#define BCM5481_ASTAT_ANHCD (7 << 8) +-#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) +-#define BCM5481_ASTAT_1KBTFD (0x7) +-#define BCM5481_ASTAT_1KBTHD (0x6) +-#define BCM5481_ASTAT_100BTXFD (0x5) +-#define BCM5481_ASTAT_100BTXHD (0x3) +- +-// end BCM5481 specifics +- + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ +- ++ +--- a/Embedded/src/GbE/iegbe_osdep.h ++++ b/Embedded/src/GbE/iegbe_osdep.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +--- a/Embedded/src/GbE/iegbe_param.c ++++ b/Embedded/src/GbE/iegbe_param.c +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -239,11 +239,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte + #define MAX_TXABSDELAY 0xFFFF + #define MIN_TXABSDELAY 0 + +-#ifdef IEGBE_GBE_WORKAROUND +-#define DEFAULT_ITR 0 +-#else + #define DEFAULT_ITR 8000 +-#endif + + + #define MAX_ITR 100000 +@@ -373,7 +369,7 @@ iegbe_check_options(struct iegbe_adapter + tx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_tx_queues; i++) + tx_ring[i].count = tx_ring->count; + } + { /* Receive Descriptor Count */ +@@ -403,7 +399,7 @@ iegbe_check_options(struct iegbe_adapter + rx_ring->count = opt.def; + } + #endif +- for (i = 0; i < adapter->num_queues; i++) ++ for (i = 0; i < adapter->num_rx_queues; i++) + rx_ring[i].count = rx_ring->count; + } + { /* Checksum Offload Enable/Disable */ +--- a/Embedded/src/GbE/kcompat.c ++++ b/Embedded/src/GbE/kcompat.c +@@ -1,8 +1,8 @@ +-/************************************************************
+-
++/************************************************************ ++ + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,183 +22,192 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 +-
+- Contact Information:
+-
+- Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226
+-
+-**************************************************************/
+-/**************************************************************************
+- * @ingroup KCOMPAT_GENERAL
+- *
+- * @file kcompat.c
+- *
+- * @description
+- *
+- *
+- **************************************************************************/
+-#include "kcompat.h"
+-
+-/*************************************************************/
+-/* 2.4.13 => 2.4.3 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) )
+-
+-/**************************************/
+-/* PCI DMA MAPPING */
+-
+-#if defined(CONFIG_HIGHMEM)
+-
+-#ifndef PCI_DRAM_OFFSET
+-#define PCI_DRAM_OFFSET 0
+-#endif
+-
+-u64 _kc_pci_map_page(struct pci_dev *dev,
+- struct page *page,
+- unsigned long offset,
+- size_t size,
+- int direction)
+-{
+- u64 ret_val;
+- ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset +
+- PCI_DRAM_OFFSET);
+- return ret_val;
+-}
+-
+-#else /* CONFIG_HIGHMEM */
+-
+-u64 _kc_pci_map_page(struct pci_dev *dev,
+- struct page *page,
+- unsigned long offset,
+- size_t size,
+- int direction)
+-{
+- return pci_map_single(dev, (void *)page_address(page) + offset,
+- size, direction);
+-}
+-
+-#endif /* CONFIG_HIGHMEM */
+-
+-void _kc_pci_unmap_page(struct pci_dev *dev,
+- u64 dma_addr,
+- size_t size,
+- int direction)
+-{
+- return pci_unmap_single(dev, dma_addr, size, direction);
+-}
+-
+-#endif /* 2.4.13 => 2.4.3 */
+-
+-
+-/*****************************************************************************/
+-/* 2.4.3 => 2.4.0 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) )
+-
+-/**************************************/
+-/* PCI DRIVER API */
+-
+-int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
+-{
+- if(!pci_dma_supported(dev, mask)) {
+- return -EIO;
+- }
+- dev->dma_mask = mask;
+- return 0;
+-}
+-
+-int _kc_pci_request_regions(struct pci_dev *dev, char *res_name)
+-{
+- int i;
+-
+- for (i = 0; i < 0x6; i++) {
+- if (pci_resource_len(dev, i) == 0) {
+- continue;
+- }
+- if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
+- if (!request_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i), res_name)) {
+- pci_release_regions(dev);
+- return -EBUSY;
+- }
+- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
+- if (!request_mem_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i),
+- res_name)) {
+- pci_release_regions(dev);
+- return -EBUSY;
+- }
+- }
+- }
+- return 0;
+-}
+-
+-void _kc_pci_release_regions(struct pci_dev *dev)
+-{
+- int i;
+-
+- for (i = 0; i < 0x6; i++) {
+- if (pci_resource_len(dev, i) == 0) {
+- continue;
+- }
+- if (pci_resource_flags(dev, i) & IORESOURCE_IO){
+- release_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i));
+- } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
+- release_mem_region(pci_resource_start(dev, i),
+- pci_resource_len(dev, i));
+- }
+- }
+-}
+-
+-/**************************************/
+-/* NETWORK DRIVER API */
+-
+-struct net_device * _kc_alloc_etherdev(int sizeof_priv)
+-{
+- struct net_device *dev;
+- int alloc_size;
+-
+- alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f;
+-
+- dev = kmalloc(alloc_size, GFP_KERNEL);
+-
+- if (!dev) { return NULL; }
+-
+- memset(dev, 0, alloc_size);
+-
+- if (sizeof_priv) {
+- dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f);
+- }
+- dev->name[0] = '\0';
+-
+- ether_setup(dev);
+-
+- return dev;
+-}
+-
+-int _kc_is_valid_ether_addr(u8 *addr)
+-{
+- const char zaddr[0x6] = {0,};
+-
+- return !(addr[0]&1) && memcmp( addr, zaddr, 0x6);
+-}
+-
+-#endif /* 2.4.3 => 2.4.0 */
+-
+-
+-/*****************************************************************/
+-/* 2.4.6 => 2.4.3 */
+-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) )
+-
+-int _kc_pci_set_power_state(struct pci_dev *dev, int state)
+-{ return 0; }
+-int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer)
+-{ return 0; }
+-int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer)
+-{ return 0; }
+-int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable)
+-{ return 0; }
+-
+-#endif /* 2.4.6 => 2.4.3 */
+-
+-
++ version: Embedded.Release.Patch.L.1.0.7-5 ++ ++ Contact Information: ++ ++ Intel Corporation, 5000 W Chandler Blvd, Chandler, AZ 85226 ++ ++**************************************************************/ ++/************************************************************************** ++ * @ingroup KCOMPAT_GENERAL ++ * ++ * @file kcompat.c ++ * ++ * @description ++ * ++ * ++ **************************************************************************/ ++#include "kcompat.h" ++ ++/*************************************************************/ ++/* 2.4.13 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0xd) ) ++ ++/**************************************/ ++/* PCI DMA MAPPING */ ++ ++#if defined(CONFIG_HIGHMEM) ++ ++#ifndef PCI_DRAM_OFFSET ++#define PCI_DRAM_OFFSET 0 ++#endif ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ u64 ret_val; ++ ret_val = (((u64)(page - mem_map) << PAGE_SHIFT) + offset + ++ PCI_DRAM_OFFSET); ++ return ret_val; ++} ++ ++#else /* CONFIG_HIGHMEM */ ++ ++u64 _kc_pci_map_page(struct pci_dev *dev, ++ struct page *page, ++ unsigned long offset, ++ size_t size, ++ int direction) ++{ ++ return pci_map_single(dev, (void *)page_address(page) + offset, ++ size, direction); ++} ++ ++#endif /* CONFIG_HIGHMEM */ ++ ++void _kc_pci_unmap_page(struct pci_dev *dev, ++ u64 dma_addr, ++ size_t size, ++ int direction) ++{ ++ return pci_unmap_single(dev, dma_addr, size, direction); ++} ++ ++#endif /* 2.4.13 => 2.4.3 */ ++ ++ ++/*****************************************************************************/ ++/* 2.4.3 => 2.4.0 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x3) ) ++ ++/**************************************/ ++/* PCI DRIVER API */ ++ ++int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) ++{ ++ if(!pci_dma_supported(dev, mask)) { ++ return -EIO; ++ } ++ dev->dma_mask = mask; ++ return 0; ++} ++ ++int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO) { ++ if (!request_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ if (!request_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i), ++ res_name)) { ++ pci_release_regions(dev); ++ return -EBUSY; ++ } ++ } ++ } ++ return 0; ++} ++ ++void _kc_pci_release_regions(struct pci_dev *dev) ++{ ++ int i; ++ ++ for (i = 0; i < 0x6; i++) { ++ if (pci_resource_len(dev, i) == 0) { ++ continue; ++ } ++ if (pci_resource_flags(dev, i) & IORESOURCE_IO){ ++ release_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { ++ release_mem_region(pci_resource_start(dev, i), ++ pci_resource_len(dev, i)); ++ } ++ } ++} ++ ++/**************************************/ ++/* NETWORK DRIVER API */ ++ ++struct net_device * _kc_alloc_etherdev(int sizeof_priv) ++{ ++ struct net_device *dev; ++ int alloc_size; ++ ++ alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 0x1f; ++ ++ dev = kmalloc(alloc_size, GFP_KERNEL); ++ ++ if (!dev) { return NULL; } ++ ++ memset(dev, 0, alloc_size); ++ ++ if (sizeof_priv) { ++ dev->priv = (void *) (((unsigned long)(dev + 1) + 0x1f) & ~0x1f); ++ } ++ dev->name[0] = '\0'; ++ ++ ether_setup(dev); ++ ++ return dev; ++} ++ ++int _kc_is_valid_ether_addr(u8 *addr) ++{ ++ const char zaddr[0x6] = {0,}; ++ ++ return !(addr[0]&1) && memcmp( addr, zaddr, 0x6); ++} ++ ++#endif /* 2.4.3 => 2.4.0 */ ++ ++ ++/*****************************************************************/ ++/* 2.4.6 => 2.4.3 */ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(0x2,0x4,0x6) ) ++ ++int _kc_pci_set_power_state(struct pci_dev *dev, int state) ++{ return 0; } ++int _kc_pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ return 0; } ++int _kc_pci_restore_state(struct pci_dev *pdev, u32 *buffer) ++{ return 0; } ++int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) ++{ return 0; } ++ ++#endif /* 2.4.6 => 2.4.3 */ ++ ++ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++void dump_stack(void) ++{ ++} ++ ++#endif /* 2.4.24 */ ++ +--- a/Embedded/src/GbE/kcompat_ethtool.c ++++ b/Embedded/src/GbE/kcompat_ethtool.c +@@ -2,7 +2,7 @@ + /* + * GPL LICENSE SUMMARY + * +- * Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ + * Contact Information: + * Intel Corporation + * +- * version: Embedded.L.1.0.34 ++ * version: Embedded.Release.Patch.L.1.0.7-5 + */ + + /************************************************************************** +@@ -779,6 +779,7 @@ static int ethtool_get_stats(struct net_ + } + + /* The main entry point in this file. Called from net/core/dev.c */ ++ + #define ETHTOOL_OPS_COMPAT + int ethtool_ioctl(struct ifreq *ifr) + { +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -2,7 +2,7 @@ + + GPL LICENSE SUMMARY + +- Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++ Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -22,7 +22,7 @@ GPL LICENSE SUMMARY + Contact Information: + Intel Corporation + +- version: Embedded.L.1.0.34 ++ version: Embedded.Release.Patch.L.1.0.7-5 + + Contact Information: + +@@ -69,15 +69,6 @@ GPL LICENSE SUMMARY + #define CONFIG_NET_POLL_CONTROLLER + #endif + +-#ifdef E1000_NAPI +-#undef CONFIG_E1000_NAPI +-#define CONFIG_E1000_NAPI +-#endif +- +-#ifdef E1000_NO_NAPI +-#undef CONFIG_E1000_NAPI +-#endif +- + #ifndef module_param + #define module_param(v,t,p) MODULE_PARM(v, "i"); + #endif +@@ -554,35 +545,14 @@ extern void _kc_pci_unmap_page(struct pc + #endif + + /*****************************************************************************/ +-/* 2.4.23 => 2.4.22 */ +-#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) +-#ifdef CONFIG_E1000_NAPI +-#ifndef netif_poll_disable +-#define netif_poll_disable(x) _kc_netif_poll_disable(x) +-static inline void _kc_netif_poll_disable(struct net_device *netdev) +-{ +- while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { +- /* No hurry */ +- current->state = TASK_INTERRUPTIBLE; +- schedule_timeout(1); +- } +-} +-#endif +-#ifndef netif_poll_enable +-#define netif_poll_enable(x) _kc_netif_poll_enable(x) +-static inline void _kc_netif_poll_enable(struct net_device *netdev) +-{ +- clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); +-} +-#endif +-#endif +-#endif +- +-/*****************************************************************************/ + /* 2.5.28 => 2.4.23 */ + #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) ++static inline void _kc_synchronize_irq(void) { barrier(); } ++#else + static inline void _kc_synchronize_irq() { synchronize_irq(); } ++#endif /* 2.4.23 */ + #undef synchronize_irq + #define synchronize_irq(X) _kc_synchronize_irq() + +@@ -747,6 +717,37 @@ static inline struct mii_ioctl_data *_kc + #define skb_header_cloned(x) 0 + #endif /* SKB_DATAREF_SHIFT not defined */ + ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) ++ ++#define ioread32(addr) readl(addr) ++#define iowrite32(val,addr) writel(val,addr) ++ ++#endif /* 2.6.10 */ ++ ++#ifndef DEFINE_SPINLOCK ++#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED ++#endif /* DEFINE_SPINLOCK */ ++ ++#ifndef PCI_COMMAND_INTX_DISABLE ++#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ ++#endif /* PCI_COMMAND_INTX_DISABLE */ ++ ++#ifndef ETH_GSTRING_LEN ++#define ETH_GSTRING_LEN 32 ++#endif /* ETH_GSTRING_LEN */ ++ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,24) ) ++ ++extern void dump_stack(void); ++ ++#undef register_reboot_notifier ++#define register_reboot_notifier(a) ++ ++#undef unregister_reboot_notifier ++#define unregister_reboot_notifier(a) ++ ++#endif /* 2.4.24 */ ++ + #endif /* _KCOMPAT_H_ */ + + +--- a/Embedded/src/GbE/Makefile ++++ b/Embedded/src/GbE/Makefile +@@ -1,6 +1,6 @@ + # GPL LICENSE SUMMARY + # +-# Copyright(c) 2007,2008 Intel Corporation. All rights reserved. ++# Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of version 2 of the GNU General Public License as +@@ -20,7 +20,7 @@ + # Contact Information: + # Intel Corporation + # +-# version: Embedded.L.1.0.34 ++# version: Embedded.Release.Patch.L.1.0.7-5 + + ########################################################################### + # Driver files +@@ -35,6 +35,8 @@ MDIO_PHONY_CFILES = gcu.c + MDIO_CFILES = gcu_main.c gcu_if.c + MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h kcompat.h + ++KVER=$(shell uname -r) ++ + # + # Variables: + # KSRC (path to kernel source to build against) +@@ -50,45 +52,16 @@ MDIO_HFILES = gcu.h gcu_if.h gcu_reg.h k + + # set KSRC, KOBJ, and EXTERNAL_MDIO to default values of not already set + # +-KOBJ ?= /usr/src/kernels/linux +-KSRC ?= /usr/src/kernels/linux ++#KOBJ=/usr/src/kernels/linux ++#KSRC=/usr/src/kernels/linux ++#KSRC=$(KOBJ) + EXTERNAL_MDIO ?= 1 + GBE_NAME = iegbe + GCU_NAME = gcu + +-# By default the workaround for the IEGBE writeback issue is enabled +-# +-IEGBE_GBE_WORKAROUND ?= 0 +- +-# If the platform only supports 10/100 this variable needs to be set +-# so the default advertisement is set appropriately. +-# By default, this variable will be disabled. +-# +-IEGBE_10_100_ONLY ?= 0 +- +-# check for version.h and autoconf.h for running kernel in /boot (SUSE) +-ifneq (,$(wildcard /boot/vmlinuz.version.h)) +- VERSION_FILE := /boot/vmlinuz.version.h +- CONFIG_FILE := /boot/vmlinuz.autoconf.h +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | \ +- grep UTS_RELEASE | awk '{ print $$3 }' | sed 's/\"//g') +- ifeq ($(KVER),$(shell uname -r)) +- # set up include path to override headers from kernel source +- x:=$(shell rm -rf include) +- x:=$(shell mkdir -p include/linux) +- x:=$(shell cp /boot/vmlinuz.version.h include/linux/version.h) +- x:=$(shell cp /boot/vmlinuz.autoconf.h include/linux/autoconf.h) +- CFLAGS += -I./include +- else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +- endif +-else +- VERSION_FILE := $(KOBJ)/include/linux/version.h +- UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +- CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h +-endif ++VERSION_FILE := $(KSRC)/include/linux/version.h ++UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h ++CONFIG_FILE := $(KSRC)/include/linux/autoconf.h + + ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) +@@ -98,83 +71,8 @@ ifeq (,$(wildcard $(CONFIG_FILE))) + $(error Linux kernel source not configured - missing autoconf.h) + endif + +-# as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +-# so check that file for kernel version string instead of version.h +-USE_UTS_REL := $(shell [ -f $(UTS_REL_FILE) ] && echo "1") +- +-# pick a compiler +-ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version))) +- CC := kgcc gcc cc +-else +- CC := gcc cc +-endif +-test_cc = $(shell $(cc) --version > /dev/null 2>&1 && echo $(cc)) +-CC := $(foreach cc, $(CC), $(test_cc)) +-CC := $(firstword $(CC)) +-ifeq (,$(CC)) +- $(error Compiler not found) +-endif +- +-# we need to know what platform the driver is being built on +-# some additional features are only built on Intel platforms +-ARCH := $(shell uname -m | sed 's/i.86/i386/') +-ifeq ($(ARCH),alpha) +- CFLAGS += -ffixed-8 -mno-fp-regs +-endif +-ifeq ($(ARCH),x86_64) +- CFLAGS += -mcmodel=kernel -mno-red-zone +-endif +-ifeq ($(ARCH),ppc) +- CFLAGS += -msoft-float +-endif +-ifeq ($(ARCH),ppc64) +- CFLAGS += -m64 -msoft-float +- LDFLAGS += -melf64ppc +-endif +- +-# standard flags for module builds +-CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +-CFLAGS += -I$(KSRC)/include -I. +-CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \ +- echo "-DMODVERSIONS -DEXPORT_SYMTAB \ +- -include $(KSRC)/include/linux/modversions.h") +- +-ifeq ($(IEGBE_GBE_WORKAROUND), 1) +-CFLAGS += -DIEGBE_GBE_WORKAROUND -DE1000_NO_NAPI +-endif +- +-ifeq ($(IEGBE_10_100_ONLY), 1) +-CFLAGS += -DIEGBE_10_100_ONLY +-endif +- +-CFLAGS += $(CFLAGS_EXTRA) +-#ifeq (,$(shell echo $(CFLAGS_EXTRA) | grep NAPI)) +-#CFLAGS += -DE1000_NO_NAPI +-#CFLAGS_EXTRA += -DE1000_NO_NAPI +-#endif +- +-RHC := $(KSRC)/include/linux/rhconfig.h +-ifneq (,$(wildcard $(RHC))) +- # 7.3 typo in rhconfig.h +- ifneq (,$(shell $(CC) $(CFLAGS) -E -dM $(RHC) | grep __module__bigmem)) +- CFLAGS += -D__module_bigmem +- endif +-endif +- +-# get the kernel version - we use this to find the correct install path +-ifeq ($(USE_UTS_REL), 1) +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(UTS_REL_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-else +- KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | grep UTS_RELEASE | \ +- awk '{ print $$3 }' | sed 's/\"//g') +-endif +- +-KKVER := $(shell echo $(KVER) | \ +- awk '{ if ($$0 ~ /2\.[6-9]\./) print "1"; else print "0"}') +-ifeq ($(KKVER), 0) +- $(error *** Aborting the build. \ +- *** This driver is not supported on kernel versions older than 2.6.18) ++ifeq (,$(wildcard $(UTS_REL_FILE))) ++ $(error Linux kernel source not configured - missing utsrelease.h) + endif + + # set the install path +@@ -202,11 +100,11 @@ ifneq ($(SMP),$(shell uname -a | grep SM + endif + + ifeq ($(SMP),1) +- CFLAGS += -D__SMP__ ++ EXTRA_CFLAGS += -D__SMP__ + endif + + ifeq ($(EXTERNAL_MDIO), 1) +- CFLAGS += -DEXTERNAL_MDIO ++ EXTRA_CFLAGS += -DEXTERNAL_MDIO + endif + + ########################################################################### +@@ -223,7 +121,6 @@ MANSECTION = 7 + MANFILE = $(TARGET:.ko=.$(MANSECTION)) + + ifneq ($(PATCHLEVEL),) +- EXTRA_CFLAGS += $(CFLAGS_EXTRA) + obj-m += $(TARGET:.ko=.o) + iegbe-objs := $(CFILES:.c=.o) + ifeq ($(EXTERNAL_MDIO),1) +--- a/filelist ++++ b/filelist +@@ -1,41 +1,3 @@ +-Embedded/Makefile +-Embedded/environment.mk +-Embedded/src/1588/1588.c +-Embedded/src/1588/1588.h +-Embedded/src/1588/IxTimeSyncAcc_p.h +-Embedded/src/1588/Makefile +-Embedded/src/1588/ixtimesyncacc.c +-Embedded/src/1588/ixtimesyncacc.h +-Embedded/src/1588/linux_ioctls.h +-Embedded/src/CAN/Makefile +-Embedded/src/CAN/can_fifo.c +-Embedded/src/CAN/can_fifo.h +-Embedded/src/CAN/can_ioctl.h +-Embedded/src/CAN/can_main.c +-Embedded/src/CAN/can_main.h +-Embedded/src/CAN/can_port.h +-Embedded/src/CAN/icp_can.c +-Embedded/src/CAN/icp_can.h +-Embedded/src/CAN/icp_can_regs.h +-Embedded/src/CAN/icp_can_types.h +-Embedded/src/CAN/icp_can_user.h +-Embedded/src/EDMA/Makefile +-Embedded/src/EDMA/dma.h +-Embedded/src/EDMA/dma_api.h +-Embedded/src/EDMA/dma_client_api.c +-Embedded/src/EDMA/dma_common.c +-Embedded/src/EDMA/dma_internals.h +-Embedded/src/EDMA/dma_linux.c +-Embedded/src/EDMA/os/os.c +-Embedded/src/EDMA/os/os.h +-Embedded/src/EDMA/os/os_list.c +-Embedded/src/EDMA/os/os_list.h +-Embedded/src/EDMA/os/os_types.h +-Embedded/src/GPIO/Makefile +-Embedded/src/GPIO/common.h +-Embedded/src/GPIO/gpio.h +-Embedded/src/GPIO/gpio_ref.c +-Embedded/src/GPIO/linux_ioctls.h + Embedded/src/GbE/Makefile + Embedded/src/GbE/gcu.h + Embedded/src/GbE/gcu_if.c +@@ -55,16 +17,6 @@ Embedded/src/GbE/iegbe_param.c + Embedded/src/GbE/kcompat.c + Embedded/src/GbE/kcompat.h + Embedded/src/GbE/kcompat_ethtool.c +-Embedded/src/WDT/Makefile +-Embedded/src/WDT/iwdt.c +-Embedded/src/WDT/iwdt.h +-Embedded/src/patches/Intel_EP80579_RHEL5.patch +-Embedded/src/patches/pci.ids_RHEL5.patch + LICENSE.GPL +-build_system/build_files/Core/ia.mk +-build_system/build_files/OS/linux_2.6.mk +-build_system/build_files/OS/linux_2.6_kernel_space_rules.mk +-build_system/build_files/common.mk +-build_system/build_files/rules.mk + filelist + versionfile +--- a/versionfile ++++ b/versionfile +@@ -1,4 +1,4 @@ +-PACKAGE_TYPE=Embedded ++PACKAGE_TYPE=Embedded.Release.Patch + + PACKAGE_OS=L + +@@ -6,4 +6,6 @@ PACKAGE_VERSION_MAJOR_NUMBER=1 + + PACKAGE_VERSION_MINOR_NUMBER=0 + +-PACKAGE_VERSION_PATCH_NUMBER=34 ++PACKAGE_VERSION_PATCH_NUMBER=7 ++ ++PACKAGE_VERSION_BUILD_NUMBER=5 diff --git a/package/system/ep80579-drivers/patches/002-cflags_cleanup.patch b/package/system/ep80579-drivers/patches/002-cflags_cleanup.patch new file mode 100644 index 0000000000..f897527956 --- /dev/null +++ b/package/system/ep80579-drivers/patches/002-cflags_cleanup.patch @@ -0,0 +1,22 @@ +--- a/build_system/build_files/common.mk ++++ b/build_system/build_files/common.mk +@@ -122,7 +122,7 @@ CC=$(COMPILER) + LD=$(LINKER) + AR=$(ARCHIVER) + +-CFLAGS+=-O2 ++#CFLAGS+=-O2 + + + PWD= $(shell pwd) +--- a/build_system/build_files/OS/linux_2.6.mk ++++ b/build_system/build_files/OS/linux_2.6.mk +@@ -80,7 +80,7 @@ endif + + + ifeq ($(OS_LEVEL), kernel_space) +-CFLAGS+= ++#CFLAGS+= + endif + + diff --git a/package/system/ep80579-drivers/patches/003-new_irqf_constants.patch b/package/system/ep80579-drivers/patches/003-new_irqf_constants.patch new file mode 100644 index 0000000000..af231f2184 --- /dev/null +++ b/package/system/ep80579-drivers/patches/003-new_irqf_constants.patch @@ -0,0 +1,53 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -291,7 +291,7 @@ int pci_probe(struct pci_dev *dev, const + + } + +- if ( request_irq(dev->irq, ×ync_isr, SA_SHIRQ, DRIVERNAME, ++ if ( request_irq(dev->irq, ×ync_isr, IRQF_SHARED, DRIVERNAME, + &g_drvr_data) ) + { + printk("%s-pci_probe: irq\n", DRIVERNAME); +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -424,7 +424,7 @@ int can_open(struct inode *inode, struct + err = request_irq(
+ can_os->irq,
+ can_irq_handler,
+- SA_SHIRQ,
++ IRQF_SHARED,
+ iminor(can_os->inode) ? CAN_PROC_1 : CAN_PROC_0,
+ &(g_can_os[iminor(can_os->inode)])
+ );
+--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -367,7 +367,7 @@ int32_t edma_resume(struct pci_dev *dev) + return -ENODEV; + } + +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +@@ -829,7 +829,7 @@ int32_t edma_probe(struct pci_dev * dev, + /* + * Obtain a (shared) Interrupt Request (IRQ) Line from the OS. + */ +- if (request_irq(dev->irq, &edma_irq_handler, SA_SHIRQ, ++ if (request_irq(dev->irq, &edma_irq_handler, IRQF_SHARED, + g_char_drvr_name, dev) ) + { + +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -1461,7 +1461,7 @@ static int __init wdt_init_one(struct pc + + /* Request irq only if wdt_irq is other than 0 */ + if (wdt_irq) { +- if (request_irq(wdt_irq, wdt_isr, SA_INTERRUPT | SA_SHIRQ, ++ if (request_irq(wdt_irq, wdt_isr, IRQF_DISABLED | IRQF_SHARED, + "iwdt", &wdt_miscdev)) { + printk("IRQ %d is not free.\n", wdt_irq); + return -EIO; diff --git a/package/system/ep80579-drivers/patches/100-iegbe_netdev_ops.patch b/package/system/ep80579-drivers/patches/100-iegbe_netdev_ops.patch new file mode 100644 index 0000000000..162449c69b --- /dev/null +++ b/package/system/ep80579-drivers/patches/100-iegbe_netdev_ops.patch @@ -0,0 +1,56 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -724,6 +724,26 @@ static void iegbe_dump_eeprom(struct ieg + kfree(data); + } + ++static const struct net_device_ops iegbe_netdev_ops = { ++ .ndo_open = iegbe_open, ++ .ndo_stop = iegbe_close, ++ .ndo_start_xmit = iegbe_xmit_frame, ++ .ndo_get_stats = iegbe_get_stats, ++ .ndo_set_rx_mode = iegbe_set_rx_mode, ++ .ndo_set_mac_address = iegbe_set_mac, ++ .ndo_tx_timeout = iegbe_tx_timeout, ++ .ndo_change_mtu = iegbe_change_mtu, ++ .ndo_do_ioctl = iegbe_ioctl, ++ .ndo_validate_addr = eth_validate_addr, ++ ++ .ndo_vlan_rx_register = iegbe_vlan_rx_register, ++ .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid, ++ .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = iegbe_netpoll, ++#endif ++}; ++ + /** + * iegbe_probe - Device Initialization Routine + * @pdev: PCI device information struct +@@ -800,24 +820,11 @@ static int __devinit iegbe_probe(struct + if (!hw->hw_addr) + goto err_ioremap; + +- netdev->open = &iegbe_open; +- netdev->stop = &iegbe_close; +- netdev->hard_start_xmit = &iegbe_xmit_frame; +- netdev->get_stats = &iegbe_get_stats; +- netdev->set_rx_mode = &iegbe_set_rx_mode; +- netdev->set_mac_address = &iegbe_set_mac; +- netdev->change_mtu = &iegbe_change_mtu; +- netdev->do_ioctl = &iegbe_ioctl; ++ netdev->netdev_ops = &iegbe_netdev_ops; + set_ethtool_ops(netdev); +- netdev->tx_timeout = &iegbe_tx_timeout; + netdev->watchdog_timeo = 5 * HZ; + netif_napi_add(netdev, &adapter->napi, iegbe_clean, 64); +- netdev->vlan_rx_register = iegbe_vlan_rx_register; +- netdev->vlan_rx_add_vid = iegbe_vlan_rx_add_vid; +- netdev->vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid; +-#ifdef CONFIG_NET_POLL_CONTROLLER +- netdev->poll_controller = iegbe_netpoll; +-#endif ++ + strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); + + diff --git a/package/system/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch b/package/system/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch new file mode 100644 index 0000000000..921d464bad --- /dev/null +++ b/package/system/ep80579-drivers/patches/101-iegbe_fix_napi_interface.patch @@ -0,0 +1,41 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3465,12 +3465,12 @@ static irqreturn_t iegbe_intr_msi(int ir + printk("Critical error! ICR = 0x%x\n", icr); + return IRQ_HANDLED; + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + iegbe_irq_enable(adapter); + +@@ -3527,12 +3527,12 @@ iegbe_intr(int irq, void *data) + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + E1000_WRITE_FLUSH(&adapter->hw); + } +- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) { ++ if (likely(napi_schedule_prep(&adapter->napi))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; +- __netif_rx_schedule(netdev, &adapter->napi); ++ __napi_schedule(&adapter->napi); + } else + /* this really should not happen! if it does it is basically a + * bug, but not a hard error, so enable ints and continue */ +@@ -3574,7 +3574,7 @@ static int iegbe_clean(struct napi_struc + if (work_done < budget) { + if (likely(adapter->itr_setting & 3)) + iegbe_set_itr(adapter); +- netif_rx_complete(poll_dev, napi); ++ napi_complete(napi); + iegbe_irq_enable(adapter); + } + diff --git a/package/system/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch b/package/system/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch new file mode 100644 index 0000000000..f7ca62709d --- /dev/null +++ b/package/system/ep80579-drivers/patches/102-iegbe_nuke_polling_netdev.patch @@ -0,0 +1,103 @@ +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -316,7 +316,6 @@ struct iegbe_adapter { + int cleaned_count); + struct iegbe_rx_ring *rx_ring; /* One per active queue */ + struct napi_struct napi; +- struct net_device *polling_netdev; /* One per active queue */ + + int num_tx_queues; + int num_rx_queues; +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -763,7 +763,7 @@ static int __devinit iegbe_probe(struct + struct iegbe_hw *hw; + + static int cards_found = 0; +- int i, err, pci_using_dac; ++ int err, pci_using_dac; + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + int bars; +@@ -984,11 +984,8 @@ err_eeprom: + iegbe_phy_hw_reset(hw); + if (hw->flash_address) + iounmap(hw->flash_address); +- for (i = 0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + err_sw_init: + iounmap(hw->hw_addr); + err_ioremap: +@@ -1017,7 +1014,6 @@ iegbe_remove(struct pci_dev *pdev) + struct net_device *netdev = pci_get_drvdata(pdev); + struct iegbe_adapter *adapter = netdev_priv(netdev); + uint32_t manc; +- int i; + + if(adapter->hw.mac_type >= iegbe_82540 + && adapter->hw.mac_type != iegbe_icp_xxxx +@@ -1030,15 +1026,11 @@ iegbe_remove(struct pci_dev *pdev) + } + + unregister_netdev(netdev); +- for (i = 0x0; i < adapter->num_rx_queues; i++) +- dev_put(&adapter->polling_netdev[i]); +- + if(!iegbe_check_phy_reset_block(&adapter->hw)) { + iegbe_phy_hw_reset(&adapter->hw); + } + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); +- kfree(adapter->polling_netdev); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); +@@ -1061,7 +1053,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + struct iegbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +- int i; + + /* PCI config space info */ + +@@ -1111,11 +1102,6 @@ iegbe_sw_init(struct iegbe_adapter *adap + return -ENOMEM; + } + +- for (i = 0; i < adapter->num_rx_queues; i++) { +- adapter->polling_netdev[i].priv = adapter; +- dev_hold(&adapter->polling_netdev[i]); +- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state); +- } + spin_lock_init(&adapter->tx_queue_lock); + + /* +@@ -1137,8 +1123,7 @@ iegbe_sw_init(struct iegbe_adapter *adap + * @adapter: board private structure to initialize + * + * We allocate one ring per queue at run-time since we don't know the +- * number of queues at compile-time. The polling_netdev array is +- * intended for Multiqueue, but should work fine with a single queue. ++ * number of queues at compile-time. + **/ + + static int __devinit +@@ -1158,15 +1143,6 @@ iegbe_alloc_queues(struct iegbe_adapter + return -ENOMEM; + } + +- adapter->polling_netdev = kcalloc(adapter->num_rx_queues, +- sizeof(struct net_device), +- GFP_KERNEL); +- if (!adapter->polling_netdev) { +- kfree(adapter->tx_ring); +- kfree(adapter->rx_ring); +- return -ENOMEM; +- } +- + return E1000_SUCCESS; + } + diff --git a/package/system/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch b/package/system/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch new file mode 100644 index 0000000000..71d2d54e6b --- /dev/null +++ b/package/system/ep80579-drivers/patches/103-iegbe_convert_unicast_addr_list.patch @@ -0,0 +1,60 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2161,7 +2161,8 @@ static void iegbe_set_rx_mode(struct net + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + struct iegbe_hw *hw = &adapter->hw; +- struct dev_addr_list *uc_ptr; ++ struct netdev_hw_addr *ha; ++ bool use_uc = false; + struct dev_addr_list *mc_ptr; + u32 rctl; + u32 hash_value; +@@ -2187,12 +2188,11 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- uc_ptr = NULL; + if (netdev->uc_count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +- uc_ptr = netdev->uc_list; ++ use_uc = true; + } + + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); +@@ -2210,13 +2210,20 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + * if there are not 14 addresses, go ahead and clear the filters + * -- with 82571 controllers only 0-13 entries are filled here + */ ++ i = 1; ++ if (use_uc) ++ list_for_each_entry(ha, &netdev->uc_list, list) { ++ if (i == rar_entries) ++ break; ++ iegbe_rar_set(hw, ha->addr, i++); ++ } ++ ++ WARN_ON(i == rar_entries); ++ + mc_ptr = netdev->mc_list; + +- for (i = 1; i < rar_entries; i++) { +- if (uc_ptr) { +- iegbe_rar_set(hw, uc_ptr->da_addr, i); +- uc_ptr = uc_ptr->next; +- } else if (mc_ptr) { ++ for (; i < rar_entries; i++) { ++ if (mc_ptr) { + iegbe_rar_set(hw, mc_ptr->da_addr, i); + mc_ptr = mc_ptr->next; + } else { +@@ -2226,7 +2233,6 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + E1000_WRITE_FLUSH(&adapter->hw); + } + } +- WARN_ON(uc_ptr != NULL); + + /* clear the old settings from the multicast hash table */ + diff --git a/package/system/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch b/package/system/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch new file mode 100644 index 0000000000..c6eced6a5c --- /dev/null +++ b/package/system/ep80579-drivers/patches/104-iegbe_group_address_list_and_its_count.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -2188,7 +2188,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + } + } + +- if (netdev->uc_count > rar_entries - 1) { ++ if (netdev->uc.count > rar_entries - 1) { + rctl |= E1000_RCTL_UPE; + } else if (!(netdev->flags & IFF_PROMISC)) { + rctl &= ~E1000_RCTL_UPE; +@@ -2212,7 +2212,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + */ + i = 1; + if (use_uc) +- list_for_each_entry(ha, &netdev->uc_list, list) { ++ list_for_each_entry(ha, &netdev->uc.list, list) { + if (i == rar_entries) + break; + iegbe_rar_set(hw, ha->addr, i++); diff --git a/package/system/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch b/package/system/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch new file mode 100644 index 0000000000..d5fc46f796 --- /dev/null +++ b/package/system/ep80579-drivers/patches/105-iegbe_new_dma_masks.patch @@ -0,0 +1,20 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -775,13 +775,13 @@ static int __devinit iegbe_probe(struct + if (err) + return err; + +- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) && +- !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && ++ !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + pci_using_dac = 1; + } else { +- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { +- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + E1000_ERR("No usable DMA configuration, " + "aborting\n"); diff --git a/package/system/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch b/package/system/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch new file mode 100644 index 0000000000..a08e8c7697 --- /dev/null +++ b/package/system/ep80579-drivers/patches/106-iegbe_new_irqf_constant.patch @@ -0,0 +1,12 @@ +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -944,7 +944,8 @@ iegbe_intr_test(struct iegbe_adapter *ad + *data = 0; + + /* Hook up test interrupt handler just for this test */ +- if(!request_irq(irq, &iegbe_test_intr, 0, netdev->name, netdev)) { ++ if(!request_irq(irq, &iegbe_test_intr, IRQF_PROBE_SHARED, netdev->name, ++ netdev)) { + shared_int = FALSE; + } else if(request_irq(irq, &iegbe_test_intr, IRQF_SHARED, + netdev->name, netdev)){ diff --git a/package/system/ep80579-drivers/patches/150-ocracoke_island.patch b/package/system/ep80579-drivers/patches/150-ocracoke_island.patch new file mode 100644 index 0000000000..ae74e0c905 --- /dev/null +++ b/package/system/ep80579-drivers/patches/150-ocracoke_island.patch @@ -0,0 +1,747 @@ +--- a/Embedded/src/GbE/iegbe_oem_phy.c ++++ b/Embedded/src/GbE/iegbe_oem_phy.c +@@ -65,6 +65,10 @@ static int32_t iegbe_oem_link_m88_setup( + static int32_t iegbe_oem_set_phy_mode(struct iegbe_hw *hw); + static int32_t iegbe_oem_detect_phy(struct iegbe_hw *hw); + ++static int32_t iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw); ++static int32_t bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data); ++static int32_t oi_phy_setup (struct iegbe_hw *hw); ++ + /** + * iegbe_oem_setup_link + * @hw: iegbe_hw struct containing device specific information +@@ -114,6 +118,10 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ return E1000_SUCCESS; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_link_m88_setup(hw); +@@ -121,6 +129,12 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + return ret_val; + } + break; ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_oem_link_bcm5481_setup(hw); ++ if(ret_val) { ++ return ret_val; ++ } ++ break; + default: + DEBUGOUT("Invalid PHY ID\n"); + return -E1000_ERR_PHY_TYPE; +@@ -179,6 +193,51 @@ iegbe_oem_setup_link(struct iegbe_hw *hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++/** ++ * iegbe_oem_link_bcm5481_setup ++ * @hw: iegbe_hw struct containing device specific information ++ * ++ * Returns E1000_SUCCESS, negative E1000 error code on failure ++ * ++ * copied verbatim from iegbe_oem_link_m88_setup ++ **/ ++static int32_t ++iegbe_oem_link_bcm5481_setup(struct iegbe_hw *hw) ++{ ++ int32_t ret_val; ++ uint16_t phy_data; ++ ++ //DEBUGFUNC(__func__); ++ ++ if(!hw) ++ return -1; ++ ++ /* phy_reset_disable is set in iegbe_oem_set_phy_mode */ ++ if(hw->phy_reset_disable) ++ return E1000_SUCCESS; ++ ++ // Enable MDIX in extended control reg. ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ECTRL, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ phy_data &= ~BCM5481_ECTRL_DISMDIX; ++ ret_val = iegbe_oem_write_phy_reg_ex(hw, BCM5481_ECTRL, phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to write BCM5481_ECTRL register\n"); ++ return ret_val; ++ } ++ ++ ret_val = oi_phy_setup (hw); ++ if (ret_val) ++ return ret_val; ++ ++ return E1000_SUCCESS; ++} + + /** + * iegbe_oem_link_m88_setup +@@ -340,6 +399,11 @@ iegbe_oem_force_mdi(struct iegbe_hw *hw, + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_force_mdi() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -415,6 +479,8 @@ iegbe_oem_phy_reset_dsp(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to reset on OEM PHY\n"); + break; + default: +@@ -460,6 +526,11 @@ iegbe_oem_cleanup_after_phy_reset(struct + * see iegbe_phy_force_speed_duplex, which does the following for M88 + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_cleanup_after_phy_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* +@@ -573,6 +644,11 @@ iegbe_oem_set_phy_mode(struct iegbe_hw * + * use iegbe_set_phy_mode as example + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_phy_mode() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_read_eeprom(hw, +@@ -641,6 +717,19 @@ iegbe_oem_detect_phy(struct iegbe_hw *hw + } + hw->phy_type = iegbe_phy_oem; + ++{ ++ // If MAC2 (BCM5395 switch), manually detect the phy ++ struct iegbe_adapter *adapter; ++ uint32_t device_number; ++ adapter = (struct iegbe_adapter *) hw->back; ++ device_number = PCI_SLOT(adapter->pdev->devfn); ++ if (device_number == ICP_XXXX_MAC_2) { ++ hw->phy_id = BCM5395S_PHY_ID; ++ hw->phy_revision = 0; ++ return E1000_SUCCESS; ++ } ++} ++ + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_ID1, &phy_id_high); + if(ret_val) { + DEBUGOUT("Unable to read PHY register PHY_ID1\n"); +@@ -690,6 +779,8 @@ iegbe_oem_get_tipg(struct iegbe_hw *hw) + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + phy_num = DEFAULT_ICP_XXXX_TIPG_IPGT; + break; + default: +@@ -738,6 +829,8 @@ iegbe_oem_phy_is_copper(struct iegbe_hw + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + isCopper = TRUE; + break; + default: +@@ -796,13 +889,13 @@ iegbe_oem_get_phy_dev_number(struct iegb + switch(device_number) + { + case ICP_XXXX_MAC_0: +- hw->phy_addr = 0x00; ++ hw->phy_addr = 0x01; + break; + case ICP_XXXX_MAC_1: +- hw->phy_addr = 0x01; ++ hw->phy_addr = 0x02; + break; + case ICP_XXXX_MAC_2: +- hw->phy_addr = 0x02; ++ hw->phy_addr = 0x00; + break; + default: hw->phy_addr = 0x00; + } +@@ -851,6 +944,12 @@ iegbe_oem_mii_ioctl(struct iegbe_adapter + if(!adapter || !ifr) { + return -1; + } ++ ++ // If MAC2 (BCM5395 switch) then leave now ++ if ((PCI_SLOT(adapter->pdev->devfn)) == ICP_XXXX_MAC_2) { ++ return -1; ++ } ++ + switch (data->reg_num) { + case PHY_CTRL: + if(mii_reg & MII_CR_POWER_DOWN) { +@@ -987,6 +1086,11 @@ void iegbe_oem_get_phy_regs(struct iegbe + * [10] = mdix mode + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_get_phy_regs() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + if(corrected_len > 0) { +@@ -1068,8 +1172,13 @@ iegbe_oem_phy_loopback(struct iegbe_adap + * Loopback configuration is the same for each of the supported PHYs. + */ + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_loopback() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + + adapter->hw.autoneg = FALSE; + +@@ -1182,8 +1291,14 @@ iegbe_oem_loopback_cleanup(struct iegbe_ + } + + switch (adapter->hw.phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_loopback_cleanup() has been called!\n"); ++ return; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + default: + adapter->hw.autoneg = TRUE; + +@@ -1243,6 +1358,11 @@ iegbe_oem_phy_speed_downgraded(struct ie + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *isDowngraded = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1305,6 +1425,11 @@ iegbe_oem_check_polarity(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *polarity = 0; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* return the Polarity bit in the Status register. */ +@@ -1367,6 +1492,25 @@ iegbe_oem_phy_is_full_duplex(struct iegb + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always full duplex */ ++ *isFD = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_100BTXFD: ++ *isFD = 1; ++ break; ++ default: ++ *isFD = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1423,6 +1567,25 @@ iegbe_oem_phy_is_speed_1000(struct iegbe + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000mb */ ++ *is1000 = 1; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_1KBTFD: ++ case BCM5481_ASTAT_1KBTHD: ++ *is1000 = 1; ++ break; ++ default: ++ *is1000 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, +@@ -1478,6 +1641,25 @@ iegbe_oem_phy_is_speed_100(struct iegbe_ + * see iegbe_config_mac_to_phy + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Always 1000Mb, never 100mb */ ++ *is100 = 0; ++ break; ++ ++ case BCM5481_PHY_ID: ++ ret_val = iegbe_read_phy_reg(hw, BCM5481_ASTAT, &phy_data); ++ if(ret_val) return ret_val; ++ ++ switch (BCM5481_ASTAT_HCD(phy_data)) { ++ case BCM5481_ASTAT_100BTXFD: ++ case BCM5481_ASTAT_100BTXHD: ++ *is100 = 1; ++ break; ++ default: ++ *is100 = 0; ++ } ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -1535,6 +1717,11 @@ iegbe_oem_phy_get_info(struct iegbe_hw * + * see iegbe_phy_m88_get_info + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_get_info() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* The downshift status is checked only once, after link is +@@ -1636,8 +1823,13 @@ iegbe_oem_phy_hw_reset(struct iegbe_hw * + * the M88 used in truxton. + */ + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_phy_hw_reset() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, PHY_CTRL, &phy_data); + if(ret_val) { + DEBUGOUT("Unable to read register PHY_CTRL\n"); +@@ -1699,6 +1891,8 @@ iegbe_oem_phy_init_script(struct iegbe_h + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("Nothing to do for OEM PHY Init"); + break; + default: +@@ -1735,6 +1929,11 @@ iegbe_oem_read_phy_reg_ex(struct iegbe_h + return -1; + } + ++ if (hw->phy_id == BCM5395S_PHY_ID) { ++ DEBUGOUT("WARNING: iegbe_oem_read_phy_reg_ex() has been unexpectedly called!\n"); ++ return -1; ++ } ++ + /* call the GCU func that will read the phy + * + * Make note that the M88 phy is what'll be used on Truxton. +@@ -1782,6 +1981,11 @@ iegbe_oem_set_trans_gasket(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ DEBUGOUT("WARNING: An empty iegbe_oem_set_trans_gasket() has been called!\n"); ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + /* Gasket set correctly for Marvell Phys, so nothing to do */ +@@ -1886,6 +2090,8 @@ iegbe_oem_phy_needs_reset_with_mac(struc + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + ret_val = FALSE; + break; + default: +@@ -1935,6 +2141,8 @@ iegbe_oem_config_dsp_after_link_change(s + switch (hw->phy_id) { + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: ++ case BCM5481_PHY_ID: ++ case BCM5395S_PHY_ID: + DEBUGOUT("No DSP to configure on OEM PHY"); + break; + default: +@@ -1978,6 +2186,12 @@ iegbe_oem_get_cable_length(struct iegbe_ + } + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ case BCM5481_PHY_ID: ++ *min_length = 0; ++ *max_length = iegbe_igp_cable_length_150; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + ret_val = iegbe_oem_read_phy_reg_ex(hw, +@@ -2061,6 +2275,23 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + */ + + switch (hw->phy_id) { ++ case BCM5395S_PHY_ID: ++ /* Link always up */ ++ *isUp = TRUE; ++ return E1000_SUCCESS; ++ break; ++ ++ case BCM5481_PHY_ID: ++ iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ ret_val = iegbe_oem_read_phy_reg_ex(hw, BCM5481_ESTAT, &phy_data); ++ if(ret_val) ++ { ++ DEBUGOUT("Unable to read PHY register BCM5481_ESTAT\n"); ++ return ret_val; ++ } ++ statusMask = BCM5481_ESTAT_LINK; ++ break; ++ + case M88E1000_I_PHY_ID: + case M88E1141_E_PHY_ID: + iegbe_oem_read_phy_reg_ex(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); +@@ -2092,3 +2323,210 @@ iegbe_oem_phy_is_link_up(struct iegbe_hw + #endif /* ifdef EXTERNAL_MDIO */ + } + ++ ++ ++//----- ++// Read BCM5481 expansion register ++// ++int32_t ++bcm5481_read_ex (struct iegbe_hw *hw, uint16_t reg, uint16_t *data) ++{ ++ int ret; ++ uint16_t selector; ++ uint16_t reg_data; ++ ++ // Get the current value of bits 15:12 ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, &selector); ++ if (ret) ++ return ret; ++ ++ // Select the expansion register ++ selector &= 0xf000; ++ selector |= (0xf << 8) | (reg); ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ // Read the expansion register ++ ret = iegbe_oem_read_phy_reg_ex (hw, 0x15, ®_data); ++ ++ // De-select the expansion registers. ++ selector &= 0xf000; ++ iegbe_oem_write_phy_reg_ex (hw, 0x17, selector); ++ ++ if (ret) ++ return ret; ++ ++ *data = reg_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x18 sub-register ++// ++static int32_t ++bcm5481_read_18sv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x18, sv ++ tmp_data = ((sv & BCM5481_R18H_SV_MASK) << 12) | BCM5481_R18H_SV_MCTRL; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x18, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R18H, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read reg 0x1C sub-register ++// ++int32_t ++bcm5481_read_1csv (struct iegbe_hw *hw, int sv, uint16_t *data) ++{ ++ int ret; ++ uint16_t tmp_data; ++ ++ // Select reg 0x1c, sv ++ tmp_data = ((sv & BCM5481_R1CH_SV_MASK) << BCM5481_R1CH_SV_SHIFT); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, tmp_data); ++ if(ret) ++ return ret; ++ ++ // Read reg 0x1c, sv ++ ret = iegbe_oem_read_phy_reg_ex (hw, BCM5481_R1CH, &tmp_data); ++ if(ret) ++ return ret; ++ ++ *data = tmp_data; ++ return ret; ++} ++ ++//----- ++// Read-modify-write a 0x1C register. ++// ++// hw - hardware access info. ++// reg - 0x1C register to modify. ++// data - bits which should be set. ++// mask - the '1' bits in this argument will be cleared in the data ++// read from 'reg' then 'data' will be or'd in and the result ++// will be written to 'reg'. ++ ++int32_t ++bcm5481_rmw_1csv (struct iegbe_hw *hw, uint16_t reg, uint16_t data, uint16_t mask) ++{ ++ int32_t ret; ++ uint16_t reg_data; ++ ++ ret = 0; ++ ++ ret = bcm5481_read_1csv (hw, reg, ®_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to read BCM5481 1CH register [0x%x]\n", reg); ++ return ret; ++ } ++ ++ reg_data &= ~mask; ++ reg_data |= (BCM5481_R1CH_WE | data); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, reg_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481 1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481 1CH register\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int32_t ++oi_phy_setup (struct iegbe_hw *hw) ++{ ++ int ret; ++ uint16_t pmii_data; ++ uint16_t mctrl_data; ++ uint16_t cacr_data; ++ ++ ret = 0; ++ ++ // Set low power mode via reg 0x18, sv010, bit 6 ++ // Do a read-modify-write on reg 0x18, sv010 register to preserve existing bits. ++ ret = bcm5481_read_18sv (hw, BCM5481_R18H_SV_PMII, &pmii_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_PMII register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_PMII register\n"); ++ return ret; ++ } ++ ++ // Set the LPM bit in the data just read and write back to sv010 ++ // The shadow register select bits [2:0] are set by reading the sv010 ++ // register. ++ pmii_data |= BCM5481_R18H_SV010_LPM; ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, pmii_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ ++ // Set the RGMII RXD to RXC skew bit in reg 0x18, sv111 ++ ++ if (bcm5481_read_18sv (hw, BCM5481_R18H_SV_MCTRL, &mctrl_data)) ++ { ++ DEBUGOUT("Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R18H_SV_MCTRL register\n"); ++ return ret; ++ } ++ mctrl_data |= (BCM5481_R18H_WE | BCM5481_R18H_SV111_SKEW); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R18H, mctrl_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R18H register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R18H register\n"); ++ return ret; ++ } ++ ++ // Enable RGMII transmit clock delay in reg 0x1c, sv00011 ++ ret = bcm5481_read_1csv (hw, BCM5481_R1CH_CACR, &cacr_data); ++ if (ret) ++ { ++ DEBUGOUT("Unable to read BCM5481_R1CH_CACR register\n"); ++ printk (KERN_ERR "Unable to read BCM5481_R1CH_CACR register\n"); ++ return ret; ++ } ++ ++ cacr_data |= (BCM5481_R1CH_WE | BCM5481_R1CH_CACR_TCD); ++ ++ ret = iegbe_oem_write_phy_reg_ex (hw, BCM5481_R1CH, cacr_data); ++ if(ret) ++ { ++ DEBUGOUT("Unable to write BCM5481_R1CH register\n"); ++ printk (KERN_ERR "Unable to write BCM5481_R1CH register\n"); ++ return ret; ++ } ++ ++ // Enable dual link speed indication (0x1c, sv 00010, bit 2) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_SC1, BCM5481_R1CH_SC1_LINK, BCM5481_R1CH_SC1_LINK); ++ if (ret) ++ return ret; ++ ++ // Enable link and activity on ACTIVITY LED (0x1c, sv 01001, bit 4=1, bit 3=0) ++ ret = bcm5481_rmw_1csv (hw, BCM5481_R1CH_LCTRL, BCM5481_R1CH_LCTRL_ALEN, BCM5481_R1CH_LCTRL_ALEN | BCM5481_R1CH_LCTRL_AEN); ++ if (ret) ++ return ret; ++ ++ return ret; ++} +--- a/Embedded/src/GbE/iegbe_oem_phy.h ++++ b/Embedded/src/GbE/iegbe_oem_phy.h +@@ -95,6 +95,8 @@ int32_t iegbe_oem_phy_is_link_up(struct + + #define DEFAULT_ICP_XXXX_TIPG_IPGT 8 /* Inter Packet Gap Transmit Time */ + #define ICP_XXXX_TIPG_IPGT_MASK 0x000003FFUL ++#define BCM5481_PHY_ID 0x0143BCA0 ++#define BCM5395S_PHY_ID 0x0143BCF0 + + /* Miscellaneous defines */ + #ifdef IEGBE_10_100_ONLY +@@ -103,5 +105,65 @@ int32_t iegbe_oem_phy_is_link_up(struct + #define ICP_XXXX_AUTONEG_ADV_DEFAULT 0x2F + #endif + ++/* BCM5481 specifics */ ++ ++#define BCM5481_ECTRL (0x10) ++#define BCM5481_ESTAT (0x11) ++#define BCM5481_RXERR (0x12) ++#define BCM5481_EXPRW (0x15) ++#define BCM5481_EXPACC (0x17) ++#define BCM5481_ASTAT (0x19) ++#define BCM5481_R18H (0x18) ++#define BCM5481_R1CH (0x1c) ++ ++/* indirect register access via register 18h */ ++ ++#define BCM5481_R18H_SV_MASK (7) // Mask for SV bits. ++#define BCM5481_R18H_SV_ACTRL (0) // SV000 Aux. control ++#define BCM5481_R18H_SV_10BT (1) // SV001 10Base-T ++#define BCM5481_R18H_SV_PMII (2) // SV010 Power/MII control ++#define BCM5481_R18H_SV_MTEST (4) // SV100 Misc. test ++#define BCM5481_R18H_SV_MCTRL (7) // SV111 Misc. control ++ ++#define BCM5481_R18H_SV001_POL (1 << 13) // Polarity ++#define BCM5481_R18H_SV010_LPM (1 << 6) ++#define BCM5481_R18H_SV111_SKEW (1 << 8) ++#define BCM5481_R18H_WE (1 << 15) // Write enable ++ ++// 0x1c registers ++#define BCM5481_R1CH_SV_SHIFT (10) ++#define BCM5481_R1CH_SV_MASK (0x1f) ++#define BCM5481_R1CH_SC1 (0x02) // sv00010 Spare control 1 ++#define BCM5481_R1CH_CACR (0x03) // sv00011 Clock alignment control ++#define BCM5481_R1CH_LCTRL (0x09) // sv01001 LED control ++#define BCM5481_R1CH_LEDS1 (0x0d) // sv01101 LED selector 1 ++ ++// 0x1c common ++#define BCM5481_R1CH_WE (1 << 15) // Write enable ++ ++// 0x1c, sv 00010 ++#define BCM5481_R1CH_SC1_LINK (1 << 2) // sv00010 Linkspeed ++ ++// 0x1c, sv 00011 ++#define BCM5481_R1CH_CACR_TCD (1 << 9) // sv00011 RGMII tx clock delay ++ ++// 0x1c, sv 01001 ++#define BCM5481_R1CH_LCTRL_ALEN (1 << 4) // Activity/Link enable on ACTIVITY LED ++#define BCM5481_R1CH_LCTRL_AEN (1 << 3) // Activity enable on ACTIVITY LED ++ ++#define BCM5481_ECTRL_DISMDIX (1 <<14) ++ ++#define BCM5481_MCTRL_AUTOMDIX (1 <<9) ++ ++#define BCM5481_ESTAT_LINK (1 << 8) ++ ++#define BCM5481_ASTAT_ANC (1 << 15) ++#define BCM5481_ASTAT_ANHCD (7 << 8) ++#define BCM5481_ASTAT_HCD(x) ((x >> 8) & 7) ++#define BCM5481_ASTAT_1KBTFD (0x7) ++#define BCM5481_ASTAT_1KBTHD (0x6) ++#define BCM5481_ASTAT_100BTXFD (0x5) ++#define BCM5481_ASTAT_100BTXHD (0x3) ++ + #endif /* ifndef _IEGBE_OEM_PHY_H_ */ + diff --git a/package/system/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch b/package/system/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch new file mode 100644 index 0000000000..2919466251 --- /dev/null +++ b/package/system/ep80579-drivers/patches/200-can_fix_ioctl_numbers.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/icp_can_user.h ++++ b/Embedded/src/CAN/icp_can_user.h +@@ -63,6 +63,8 @@ + #ifndef __ICP_CAN_USER_H__ + #define __ICP_CAN_USER_H__ + ++#include <linux/ioctl.h> ++ + /***************************************************************************** + * Device IO control codes. + *****************************************************************************/ diff --git a/package/system/ep80579-drivers/patches/210-can_include_linux_fs_h.patch b/package/system/ep80579-drivers/patches/210-can_include_linux_fs_h.patch new file mode 100644 index 0000000000..26c53dcea4 --- /dev/null +++ b/package/system/ep80579-drivers/patches/210-can_include_linux_fs_h.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -70,6 +70,8 @@ +
+ #include "can_main.h"
+ #include "can_ioctl.h"
++#include <linux/fs.h> ++ +
+ MODULE_AUTHOR("Intel(R) Corporation");
+ MODULE_DESCRIPTION("Controller Area Network Driver");
diff --git a/package/system/ep80579-drivers/patches/220-can_fix_irq_request.patch b/package/system/ep80579-drivers/patches/220-can_fix_irq_request.patch new file mode 100644 index 0000000000..2950cc79e5 --- /dev/null +++ b/package/system/ep80579-drivers/patches/220-can_fix_irq_request.patch @@ -0,0 +1,23 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -654,7 +654,7 @@ int can_dev_io(struct inode *inode, stru + /*****************************************************************************
+ * Interrupt handler.
+ *****************************************************************************/
+-irqreturn_t can_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t can_irq_handler(int irq, void *dev_id)
+ {
+ can_os_t *can_os = (can_os_t *) dev_id;
+ unsigned int int_status;
+--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -165,8 +165,7 @@ int can_dev_io( + + irqreturn_t can_irq_handler( + int irq, +- void *dev_id, +- struct pt_regs *regs); ++ void *dev_id); + + void can_tasklet( + unsigned long arg diff --git a/package/system/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch b/package/system/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch new file mode 100644 index 0000000000..19dbb7e0b2 --- /dev/null +++ b/package/system/ep80579-drivers/patches/230-can_remove_driver_data_direct_access.patch @@ -0,0 +1,40 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -214,8 +214,8 @@ int can_pci_probe(struct pci_dev *dev, c + spin_lock_init(&(g_can_os[can_num].int_spinlock));
+ spin_lock_init(&(g_can_os[can_num].open_spinlock));
+
+- dev->dev.driver_data = (void *) &(g_can_os[can_num]);
+- if (!dev->dev.driver_data)
++ dev_set_drvdata(&dev->dev, (void *) &(g_can_os[can_num]));
++ if (!dev_get_drvdata(&dev->dev))
+ {
+ printk("Couldn't create CAN device %d. Exiting.\n",
+ dev->device);
+@@ -237,7 +237,7 @@ int can_pci_probe(struct pci_dev *dev, c + *****************************************************************************/
+ void can_pci_remove(struct pci_dev *dev)
+ {
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+
+ iounmap(can_os->pci_remap);
+ icp_can_destroy(can_os->can);
+@@ -251,7 +251,7 @@ int can_pci_suspend(struct pci_dev *dev, + {
+ unsigned int i;
+ unsigned int int_status;
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+ int err;
+
+ /* Indicate that we are suspending */
+@@ -322,7 +322,7 @@ int can_pci_suspend(struct pci_dev *dev, + int can_pci_resume(struct pci_dev *dev)
+ {
+ unsigned int i;
+- can_os_t *can_os = dev->dev.driver_data;
++ can_os_t *can_os = dev_get_drvdata(&dev->dev);
+
+ /* Restore PCI CFG space */
+ pci_restore_state(dev);
diff --git a/package/system/ep80579-drivers/patches/300-wdt_compile_fix.patch b/package/system/ep80579-drivers/patches/300-wdt_compile_fix.patch new file mode 100644 index 0000000000..59242b80b3 --- /dev/null +++ b/package/system/ep80579-drivers/patches/300-wdt_compile_fix.patch @@ -0,0 +1,59 @@ +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -180,19 +180,19 @@ MODULE_PARM_DESC(wdt_scale, "Intel WDT s + module_param(wdt_intr_type, byte, WDT_INT_TYPE_IRQ); + MODULE_PARM_DESC(wdt_intr_type, "Intel WDT interrupt type (default SERIRQ)."); + +-module_param(wdt_margin1, uint, TIMER_MARGIN); ++module_param(wdt_margin1, uint, 0); + MODULE_PARM_DESC(wdt_margin1, "First stage Intel WDT timeout in steps of 1 ms by default."); + +-module_param(wdt_margin2, uint, TIMER_MARGIN); ++module_param(wdt_margin2, uint, 0); + MODULE_PARM_DESC(wdt_margin2, "Second stage Intel WDT timeout in steps of 1 ms by default."); + + module_param(nowayout, int, 0); + MODULE_PARM_DESC(nowayout, "Intel WDT can't be stopped once started (default=0)"); + +-module_param(wdt_index_port, int, 0x4E); ++module_param(wdt_index_port, int, 0); + MODULE_PARM_DESC(wdt_index_port, "WDT Index Port (default 0x4e)"); + +-module_param(wdt_data_port, int, 0x4E); ++module_param(wdt_data_port, int, 0); + MODULE_PARM_DESC(wdt_data_port, "WDT Data Port (default 0x4f)"); + + static int wdt_get_iobase(struct pci_dev *dev, u16 *iobase, int *irq); +@@ -218,7 +218,7 @@ static ssize_t wdt_write(struct file *fi + size_t count, loff_t * pos); + static int wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs); ++static irqreturn_t wdt_isr(int irq, void *dev_id); + static void __exit wdt_cleanup(void); + static int __init wdt_init(void); + static int __init wdt_init_one(struct pci_dev *dev, +@@ -255,7 +255,7 @@ static struct pci_driver wdt_driver = { + name: "iwdt", + id_table: lpc_pci_tbl, + probe: wdt_init_one, +- remove: __devexit(wdt_remove_one), ++ remove: __devexit_p(wdt_remove_one), + suspend: wdt_pci_suspend, + resume: wdt_pci_resume, + }; +@@ -1393,12 +1393,12 @@ static int wdt_ioctl(struct inode *inode + + /* + * Function Name: wdt_isr() +- * Parameter: int irq - irq number, void *dev_id, struct pt_regs *regs ++ * Parameter: int irq - irq number, void *dev_id + * Return Value:: IRQ_NONE - if the interrupt is not for wdt. + * IRQ_HANDLED - if it is for wdt. + * Description: This is the interrupt service routine of the WDT. + */ +-static irqreturn_t wdt_isr(int irq, void *dev_id, struct pt_regs *regs) ++static irqreturn_t wdt_isr(int irq, void *dev_id) + { + u8 val; + diff --git a/package/system/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch b/package/system/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch new file mode 100644 index 0000000000..d858aff1ff --- /dev/null +++ b/package/system/ep80579-drivers/patches/400-edma_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -149,8 +149,7 @@ int32_t edma_suspend (struct pci_dev *de + int32_t edma_resume(struct pci_dev *dev); + int32_t initialize_edma_device(struct edma_device *device); + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs); ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id); + + /* Prototypes - Misc. */ + +@@ -429,8 +428,7 @@ int32_t edma_release(struct inode * inod + * Return Values: HANDLED = 1, NOT_HANDLED = 0 + *****************************************************************************/ + +-static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id, +- struct pt_regs * regs) ++static irqreturn_t edma_irq_handler(int32_t irq, void * dev_id) + { + + uint32_t clear_bits; diff --git a/package/system/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch b/package/system/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch new file mode 100644 index 0000000000..f3f9acb1e0 --- /dev/null +++ b/package/system/ep80579-drivers/patches/500-1588_fix_irq_request_warning.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -631,7 +631,7 @@ int restore_interrupts(void) + IRQ_NONE => this device did not interrupt + + ******************************************************************************/ +-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs) ++irqreturn_t timesync_isr(int irq, void *dev_id) + { + if ( !ixTimeSyncAccEventAmmsFlagGet() && !ixTimeSyncAccEventAsmsFlagGet()&& + !ixTimeSyncAccEventAtmFlagGet() && !ixTimeSyncAccEventPpsmFlagGet()&& +--- a/Embedded/src/1588/1588.h ++++ b/Embedded/src/1588/1588.h +@@ -128,7 +128,7 @@ int pci_suspend(struct pci_dev *dev, pm_ + int pci_resume(struct pci_dev *dev);
+ int pci_probe(struct pci_dev *dev, const struct pci_device_id *id);
+ void pci_remove(struct pci_dev *dev);
+-irqreturn_t timesync_isr(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t timesync_isr(int irq, void *dev_id);
+
+ // private functions
+ int save_reg_state(void);
diff --git a/package/system/ep80579-drivers/patches/600-2.6.27_includes.patch b/package/system/ep80579-drivers/patches/600-2.6.27_includes.patch new file mode 100644 index 0000000000..c11275ece6 --- /dev/null +++ b/package/system/ep80579-drivers/patches/600-2.6.27_includes.patch @@ -0,0 +1,22 @@ +--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -65,7 +65,7 @@ + + #include <linux/interrupt.h> + #include <linux/pci.h> +-#include <asm/semaphore.h> ++#include <linux/semaphore.h> + #include <linux/spinlock.h> + #include <linux/cdev.h> + #include <asm/uaccess.h> +--- a/Embedded/src/EDMA/dma_linux.c ++++ b/Embedded/src/EDMA/dma_linux.c +@@ -87,7 +87,7 @@ + #include <linux/fcntl.h> /* O_ACCMODE */ + #include <asm/system.h> /* cli, *_flags */ + #include <asm/uaccess.h> /* copy_to_user */ +-#include <asm/semaphore.h> ++#include <linux/semaphore.h> + #include <asm/io.h> /* inb(), outb() */ + #include <linux/kmod.h> + #include <linux/ioport.h> /* request_region */ diff --git a/package/system/ep80579-drivers/patches/601-2.6.32_includes.patch b/package/system/ep80579-drivers/patches/601-2.6.32_includes.patch new file mode 100644 index 0000000000..291fb0a33d --- /dev/null +++ b/package/system/ep80579-drivers/patches/601-2.6.32_includes.patch @@ -0,0 +1,30 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -72,6 +72,7 @@ + * + ****************************************************************************/ + ++#include <linux/sched.h> + #include "1588.h" + + MODULE_AUTHOR("Intel(R) Corporation"); +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -68,6 +68,7 @@ + *
+ **************************************************************************/
+
++#include <linux/sched.h> + #include "can_main.h"
+ #include "can_ioctl.h"
+ #include <linux/fs.h> +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -137,6 +137,7 @@ + #include <linux/watchdog.h> + #include <linux/miscdevice.h> + #include <linux/interrupt.h> ++#include <linux/sched.h> + #include "iwdt.h" + + MODULE_AUTHOR("Intel(R) Corporation"); diff --git a/package/system/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch b/package/system/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch new file mode 100644 index 0000000000..ca8c1bb9ea --- /dev/null +++ b/package/system/ep80579-drivers/patches/700-iegbe_kcompat_2.6.30.patch @@ -0,0 +1,31 @@ +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -46,12 +46,6 @@ GPL LICENSE SUMMARY + #include <linux/sched.h> + #include <asm/io.h> + +-#ifndef IRQ_HANDLED +-#define irqreturn_t void +-#define IRQ_HANDLED +-#define IRQ_NONE +-#endif +- + #ifndef SET_NETDEV_DEV + #define SET_NETDEV_DEV(net, pdev) + #endif +@@ -748,6 +742,15 @@ extern void dump_stack(void); + + #endif /* 2.4.24 */ + ++/*****************************************************************************/ ++#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) ++#ifndef IRQ_HANDLED ++#define irqreturn_t void ++#define IRQ_HANDLED ++#define IRQ_NONE ++#endif ++#endif /* < 2.6.30 */ ++ + #endif /* _KCOMPAT_H_ */ + + diff --git a/package/system/ep80579-drivers/patches/701-iegbe_poll_dev.patch b/package/system/ep80579-drivers/patches/701-iegbe_poll_dev.patch new file mode 100644 index 0000000000..63a1326853 --- /dev/null +++ b/package/system/ep80579-drivers/patches/701-iegbe_poll_dev.patch @@ -0,0 +1,11 @@ +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -3534,7 +3534,7 @@ static int iegbe_clean(struct napi_struc + int tx_cleaned = 0, work_done = 0; + + /* Must NOT use netdev_priv macro here. */ +- adapter = poll_dev->priv; ++ adapter = netdev_priv(poll_dev); + + /* iegbe_clean is called per-cpu. This lock protects + * tx_ring[0] from being cleaned by multiple cpus diff --git a/package/system/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch b/package/system/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch new file mode 100644 index 0000000000..793d08d39b --- /dev/null +++ b/package/system/ep80579-drivers/patches/710-3.3-fix-generated-header-locations.patch @@ -0,0 +1,91 @@ +--- a/Embedded/src/GbE/Makefile ++++ b/Embedded/src/GbE/Makefile +@@ -60,19 +60,19 @@ GBE_NAME = iegbe + GCU_NAME = gcu + + VERSION_FILE := $(KSRC)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KSRC)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KSRC)/include/generated/autoconf.h + + ifeq (,$(wildcard $(VERSION_FILE))) + $(error Linux kernel source not configured - missing version.h) + endif + + ifeq (,$(wildcard $(CONFIG_FILE))) +- $(error Linux kernel source not configured - missing autoconf.h) ++ $(error Linux kernel source not configured - missing autoconf.h) + endif + + ifeq (,$(wildcard $(UTS_REL_FILE))) +- $(error Linux kernel source not configured - missing utsrelease.h) ++ $(error Linux kernel source not configured - missing utsrelease.h) + endif + + # set the install path +--- a/Embedded/src/1588/Makefile ++++ b/Embedded/src/1588/Makefile +@@ -97,8 +97,8 @@ OUTPUT_PATH ?= / + EXTRA_LDFLAGS += -whole-archive + + VERSION_FILE := $(KOBJ)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h + + + # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +--- a/Embedded/src/CAN/Makefile ++++ b/Embedded/src/CAN/Makefile +@@ -100,8 +100,8 @@ OUTPUT_PATH ?= / + EXTRA_LDFLAGS += -whole-archive + + VERSION_FILE := $(KOBJ)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h + + + # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +--- a/Embedded/src/EDMA/Makefile ++++ b/Embedded/src/EDMA/Makefile +@@ -114,8 +114,8 @@ OUTPUT_PATH ?= / + EXTRA_LDFLAGS += -whole-archive + + VERSION_FILE := $(KOBJ)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h + + + # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +--- a/Embedded/src/GPIO/Makefile ++++ b/Embedded/src/GPIO/Makefile +@@ -97,8 +97,8 @@ OUTPUT_PATH ?= / + EXTRA_LDFLAGS += -whole-archive + + VERSION_FILE := $(KOBJ)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h + + + # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h +--- a/Embedded/src/WDT/Makefile ++++ b/Embedded/src/WDT/Makefile +@@ -99,8 +99,8 @@ OUTPUT_PATH ?= / + EXTRA_LDFLAGS += -whole-archive + + VERSION_FILE := $(KOBJ)/include/linux/version.h +-UTS_REL_FILE := $(KSRC)/include/linux/utsrelease.h +-CONFIG_FILE := $(KOBJ)/include/linux/autoconf.h ++UTS_REL_FILE := $(KSRC)/include/generated/utsrelease.h ++CONFIG_FILE := $(KOBJ)/include/generated/autoconf.h + + + # as of 2.6.16, kernel define UTS_RELEASE has been moved to utsrelease.h diff --git a/package/system/ep80579-drivers/patches/711-3.3-gbe-fixes.patch b/package/system/ep80579-drivers/patches/711-3.3-gbe-fixes.patch new file mode 100644 index 0000000000..7b2df63984 --- /dev/null +++ b/package/system/ep80579-drivers/patches/711-3.3-gbe-fixes.patch @@ -0,0 +1,392 @@ +--- a/Embedded/src/GbE/kcompat.h ++++ b/Embedded/src/GbE/kcompat.h +@@ -590,6 +590,10 @@ static inline void _kc_synchronize_irq() + #define ETHTOOL_OPS_COMPAT + #endif + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) ++#define HAVE_NETIF_MSG 1 ++#endif ++ + #ifndef HAVE_NETIF_MSG + #define HAVE_NETIF_MSG 1 + enum { +--- a/Embedded/src/GbE/iegbe_main.c ++++ b/Embedded/src/GbE/iegbe_main.c +@@ -159,9 +159,9 @@ static void iegbe_smartspeed(struct iegb + static inline int iegbe_82547_fifo_workaround(struct iegbe_adapter *adapter, + struct sk_buff *skb); + +-static void iegbe_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); +-static void iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); +-static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); ++static bool iegbe_vlan_used(struct iegbe_adapter *adapter); ++static int iegbe_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); ++static int iegbe_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); + static void iegbe_restore_vlan(struct iegbe_adapter *adapter); + + static int iegbe_notify_reboot(struct notifier_block *, +@@ -324,8 +324,8 @@ static void iegbe_update_mng_vlan(struct + struct net_device *netdev = adapter->netdev; + u16 vid = hw->mng_cookie.vlan_id; + u16 old_vid = adapter->mng_vlan_id; +- if (adapter->vlgrp) { +- if (!vlan_group_get_device(adapter->vlgrp, vid)) { ++ if (iegbe_vlan_used(adapter)) { ++ if (!test_bit(old_vid, adapter->active_vlans)) { + if (hw->mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { + iegbe_vlan_rx_add_vid(netdev, vid); +@@ -335,7 +335,7 @@ static void iegbe_update_mng_vlan(struct + + if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && + (vid != old_vid) && +- !vlan_group_get_device(adapter->vlgrp, old_vid)) ++ !test_bit(old_vid, adapter->active_vlans)) + iegbe_vlan_rx_kill_vid(netdev, old_vid); + } else + adapter->mng_vlan_id = vid; +@@ -736,7 +736,6 @@ static const struct net_device_ops iegbe + .ndo_do_ioctl = iegbe_ioctl, + .ndo_validate_addr = eth_validate_addr, + +- .ndo_vlan_rx_register = iegbe_vlan_rx_register, + .ndo_vlan_rx_add_vid = iegbe_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = iegbe_vlan_rx_kill_vid, + #ifdef CONFIG_NET_POLL_CONTROLLER +@@ -767,7 +766,6 @@ static int __devinit iegbe_probe(struct + u16 eeprom_data = 0; + u16 eeprom_apme_mask = E1000_EEPROM_APME; + int bars; +- DECLARE_MAC_BUF(mac); + + bars = pci_select_bars(pdev, IORESOURCE_MEM); + err = pci_enable_device(pdev); +@@ -1247,8 +1245,7 @@ static int iegbe_close(struct net_device + + if ((hw->mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && +- !(adapter->vlgrp && +- vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) { ++ !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) { + iegbe_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); + } + return 0; +@@ -2163,11 +2160,13 @@ static void iegbe_set_rx_mode(struct net + struct iegbe_hw *hw = &adapter->hw; + struct netdev_hw_addr *ha; + bool use_uc = false; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + struct dev_addr_list *mc_ptr; +- u32 rctl; + u32 hash_value; +- int i, rar_entries = E1000_RAR_ENTRIES; + int mta_reg_count = E1000_NUM_MTA_REGISTERS; ++#endif ++ u32 rctl; ++ int i, rar_entries = E1000_RAR_ENTRIES; + + /* reserve RAR[14] for LAA over-write work-around */ + if (hw->mac_type == iegbe_82571) +@@ -2220,6 +2219,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + + WARN_ON(i == rar_entries); + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + mc_ptr = netdev->mc_list; + + for (; i < rar_entries; i++) { +@@ -2247,6 +2247,7 @@ int mta_reg_count = E1000_NUM_MTA_REGIST + hash_value = iegbe_hash_mc_addr(hw, mc_ptr->da_addr); + iegbe_mta_set(hw, hash_value); + } ++#endif + + if (hw->mac_type == iegbe_82542_rev2_0) + iegbe_leave_82542_rst(adapter); +@@ -2821,14 +2822,14 @@ static int iegbe_tx_map(struct iegbe_ada + * Avoid terminating buffers within evenly-aligned + * dwords. */ + if(unlikely(adapter->pcix_82544 && +- !((unsigned long)(frag->page+offset+size-1) & 4) && ++ !((unsigned long)(frag->page.p+offset+size-1) & 4) && + size > 4)) + size -= 4; + + buffer_info->length = size; + buffer_info->dma = + pci_map_page(adapter->pdev, +- frag->page, ++ frag->page.p, + offset, + size, + PCI_DMA_TODEVICE); +@@ -3131,7 +3132,7 @@ static int iegbe_xmit_frame(struct sk_bu + } + } + +- if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) { ++ if (unlikely(iegbe_vlan_used(adapter) && vlan_tx_tag_present(skb))) { + tx_flags |= E1000_TX_FLAGS_VLAN; + tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); + } +@@ -3832,10 +3833,12 @@ static bool iegbe_clean_rx_irq(struct ie + + skb->protocol = eth_type_trans(skb, netdev); + +- if (unlikely(adapter->vlgrp && ++ if (unlikely(iegbe_vlan_used(adapter) && + (status & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->special)); ++ u16 vid; ++ ++ vid = le16_to_cpu(rx_desc->special); ++ __vlan_hwaccel_put_tag(skb, vid); + } else { + netif_receive_skb(skb); + } +@@ -3986,9 +3989,10 @@ copydone: + cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))) + adapter->rx_hdr_split++; + +- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) { +- vlan_hwaccel_receive_skb(skb, adapter->vlgrp, +- le16_to_cpu(rx_desc->wb.middle.vlan)); ++ if(unlikely(iegbe_vlan_used(adapter) && (staterr & E1000_RXD_STAT_VP))) { ++ u16 vid; ++ vid = le16_to_cpu(rx_desc->wb.middle.vlan); ++ __vlan_hwaccel_put_tag(skb, vid); + } else { + netif_receive_skb(skb); + } +@@ -4496,17 +4500,25 @@ iegbe_io_write(struct iegbe_hw *hw, unsi + outl(value, port); + } + +-static void iegbe_vlan_rx_register(struct net_device *netdev, +- struct vlan_group *grp) ++static bool iegbe_vlan_used(struct iegbe_adapter *adapter) ++{ ++ u16 vid; ++ ++ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) ++ return true; ++ ++ return false; ++} ++ ++static void iegbe_vlan_mode(struct net_device *netdev, bool vlan_on) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + uint32_t ctrl, rctl; + + if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_disable(adapter); +- adapter->vlgrp = grp; + +- if(grp) { ++ if(vlan_on) { + /* enable VLAN tag insert/strip */ + ctrl = E1000_READ_REG(&adapter->hw, CTRL); + ctrl |= E1000_CTRL_VME; +@@ -4538,30 +4550,37 @@ static void iegbe_vlan_rx_register(struc + iegbe_irq_enable(adapter); + } + +-static void iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) ++static int iegbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + uint32_t vfta, index; + if((adapter->hw.mng_cookie.status & + E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && + (vid == adapter->mng_vlan_id)) { +- return; ++ return 0; + } ++ ++ if (!iegbe_vlan_used(adapter)) ++ iegbe_vlan_mode(netdev, true); ++ + /* add VID to filter table */ + index = (vid >> 0x5) & 0x7F; + vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); + vfta |= (0x1 << (vid & 0x1F)); + iegbe_write_vfta(&adapter->hw, index, vfta); ++ ++ set_bit(vid, adapter->active_vlans); ++ ++ return 0; + } + +-static void iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ++static int iegbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) + { + struct iegbe_adapter *adapter = netdev_priv(netdev); + u32 vfta, index; + + if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_disable(adapter); +- vlan_group_set_device(adapter->vlgrp, vid, NULL); + if (!test_bit(__E1000_DOWN, &adapter->flags)) + iegbe_irq_enable(adapter); + +@@ -4570,21 +4589,26 @@ static void iegbe_vlan_rx_kill_vid(struc + vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index); + vfta &= ~(0x1 << (vid & 0x1F)); + iegbe_write_vfta(&adapter->hw, index, vfta); ++ ++ clear_bit(vid, adapter->active_vlans); ++ ++ if (!iegbe_vlan_used(adapter)) ++ iegbe_vlan_mode(netdev, false); ++ ++ return 0; + } + + static void iegbe_restore_vlan(struct iegbe_adapter *adapter) + { +- iegbe_vlan_rx_register(adapter->netdev, adapter->vlgrp); +- +- if (adapter->vlgrp) { + u16 vid; +- for (vid = 0x0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { +- if (!vlan_group_get_device(adapter->vlgrp, vid)) +- continue; ++ ++ if (!iegbe_vlan_used(adapter)) ++ return; ++ ++ iegbe_vlan_mode(adapter->netdev, true); ++ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) + iegbe_vlan_rx_add_vid(adapter->netdev, vid); + } +- } +-} + + + int iegbe_set_spd_dplx(struct iegbe_adapter *adapter, u16 spddplx) +@@ -4864,10 +4888,11 @@ iegbe_resume(struct pci_dev *pdev) + default: + break; + } +-#endif + + return 0x0; + } ++#endif ++ + + #ifdef CONFIG_NET_POLL_CONTROLLER + /* +--- a/Embedded/src/GbE/iegbe_ethtool.c ++++ b/Embedded/src/GbE/iegbe_ethtool.c +@@ -327,6 +327,7 @@ iegbe_set_pauseparam(struct net_device * + return 0; + } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + static uint32_t + iegbe_get_rx_csum(struct net_device *netdev) + { +@@ -392,6 +393,7 @@ iegbe_set_tso(struct net_device *netdev, + return 0; + } + #endif /* NETIF_F_TSO */ ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) */ + + static uint32_t + iegbe_get_msglevel(struct net_device *netdev) +@@ -807,6 +809,7 @@ err_setup_rx: + E1000_82542_##R : E1000_##R; \ + return 1; } } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + static int + iegbe_reg_test(struct iegbe_adapter *adapter, uint64_t *data) + { +@@ -1710,6 +1713,7 @@ iegbe_diag_test(struct net_device *netde + } + msleep_interruptible(0xfa0); + } ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) */ + + static void + iegbe_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +@@ -1812,6 +1816,7 @@ iegbe_set_wol(struct net_device *netdev, + /* bit defines for adapter->led_status */ + #define E1000_LED_ON 0 + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + static void + iegbe_led_blink_callback(unsigned long data) + { +@@ -1864,6 +1869,7 @@ iegbe_phys_id(struct net_device *netdev, + + return 0; + } ++#endif + + static int + iegbe_nway_reset(struct net_device *netdev) +@@ -1876,11 +1882,13 @@ iegbe_nway_reset(struct net_device *netd + return 0; + } + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + static int + iegbe_get_stats_count(struct net_device *netdev) + { + return E1000_STATS_LEN; + } ++#endif + + static void + iegbe_get_ethtool_stats(struct net_device *netdev, +@@ -1936,6 +1944,8 @@ struct ethtool_ops iegbe_ethtool_ops = { + .set_ringparam = iegbe_set_ringparam, + .get_pauseparam = iegbe_get_pauseparam, + .set_pauseparam = iegbe_set_pauseparam, ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)) + .get_rx_csum = iegbe_get_rx_csum, + .set_rx_csum = iegbe_set_rx_csum, + .get_tx_csum = iegbe_get_tx_csum, +@@ -1946,11 +1956,13 @@ struct ethtool_ops iegbe_ethtool_ops = { + .get_tso = ethtool_op_get_tso, + .set_tso = iegbe_set_tso, + #endif ++ + .self_test_count = iegbe_diag_test_count, + .self_test = iegbe_diag_test, +- .get_strings = iegbe_get_strings, + .phys_id = iegbe_phys_id, + .get_stats_count = iegbe_get_stats_count, ++#endif ++ .get_strings = iegbe_get_strings, + .get_ethtool_stats = iegbe_get_ethtool_stats, + }; + +--- a/Embedded/src/GbE/gcu_main.c ++++ b/Embedded/src/GbE/gcu_main.c +@@ -93,7 +93,7 @@ static struct pci_driver gcu_driver = { + }; + + static struct gcu_adapter *global_adapter = 0; +-static spinlock_t global_adapter_spinlock = SPIN_LOCK_UNLOCKED; ++static DEFINE_SPINLOCK(global_adapter_spinlock); + static unsigned long g_intflags = 0; + + MODULE_AUTHOR("Intel(R) Corporation"); +--- a/Embedded/src/GbE/iegbe.h ++++ b/Embedded/src/GbE/iegbe.h +@@ -257,7 +257,7 @@ struct iegbe_adapter { + struct timer_list tx_fifo_stall_timer; + struct timer_list watchdog_timer; + struct timer_list phy_info_timer; +- struct vlan_group *vlgrp; ++ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + uint16_t mng_vlan_id; + uint32_t bd_number; + uint32_t rx_buffer_len; diff --git a/package/system/ep80579-drivers/patches/712-3.3-can-fixes.patch b/package/system/ep80579-drivers/patches/712-3.3-can-fixes.patch new file mode 100644 index 0000000000..f46f900931 --- /dev/null +++ b/package/system/ep80579-drivers/patches/712-3.3-can-fixes.patch @@ -0,0 +1,41 @@ +--- a/Embedded/src/CAN/can_main.c ++++ b/Embedded/src/CAN/can_main.c +@@ -72,6 +72,7 @@ + #include "can_main.h"
+ #include "can_ioctl.h"
+ #include <linux/fs.h> ++#include <linux/module.h> + +
+ MODULE_AUTHOR("Intel(R) Corporation");
+@@ -110,7 +111,7 @@ struct file_operations file_ops = { + .owner = THIS_MODULE,
+ .read = can_read,
+ .write = can_write,
+- .ioctl = can_dev_io,
++ .unlocked_ioctl = can_dev_io,
+ .open = can_open,
+ .release = can_release
+ };
+@@ -594,8 +595,7 @@ int icp_can_reset(can_os_t *can_os) + /*****************************************************************************
+ * Device IO control function. Used by user apps to configure CAN device.
+ *****************************************************************************/
+-int can_dev_io(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
++long can_dev_io(struct file *filp, unsigned int cmd, unsigned long arg)
+ {
+ can_os_t *can_os;
+ unsigned int err=0;
+--- a/Embedded/src/CAN/can_main.h ++++ b/Embedded/src/CAN/can_main.h +@@ -157,8 +157,7 @@ ssize_t can_write( + int icp_can_reset( + can_os_t *can_os); + +-int can_dev_io( +- struct inode *inode, ++long can_dev_io( + struct file *filp, + unsigned int cmd, + unsigned long arg); diff --git a/package/system/ep80579-drivers/patches/713-3.3-gpio-fixes.patch b/package/system/ep80579-drivers/patches/713-3.3-gpio-fixes.patch new file mode 100644 index 0000000000..47fb920d0a --- /dev/null +++ b/package/system/ep80579-drivers/patches/713-3.3-gpio-fixes.patch @@ -0,0 +1,33 @@ +--- a/Embedded/src/GPIO/gpio.h ++++ b/Embedded/src/GPIO/gpio.h +@@ -121,8 +121,7 @@ int gpio_init(void); + void gpio_close(void); + int gpio_open(struct inode *inode, struct file *filp); + int gpio_release(struct inode *inode, struct file *filp); +-int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +- unsigned long arg); ++long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); + + // private driver functions + int gpio_getpininfo(int Signal, char *pBuff); +@@ -134,7 +133,7 @@ struct file_operations file_ops = + .owner = THIS_MODULE, + .open = gpio_open, + .release = gpio_release, +- .ioctl = gpio_ioctl, ++ .unlocked_ioctl = gpio_ioctl, + }; + + #endif +--- a/Embedded/src/GPIO/gpio_ref.c ++++ b/Embedded/src/GPIO/gpio_ref.c +@@ -251,8 +251,7 @@ int gpio_release(struct inode *inode, st + 0 => success + < 0 => error + ******************************************************************************/ +-int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +- unsigned long arg) ++long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + gpio_ioctl_t Info; + u_int bitstr = 0; diff --git a/package/system/ep80579-drivers/patches/714-3.3-wdt-fixes.patch b/package/system/ep80579-drivers/patches/714-3.3-wdt-fixes.patch new file mode 100644 index 0000000000..60cc4aeb73 --- /dev/null +++ b/package/system/ep80579-drivers/patches/714-3.3-wdt-fixes.patch @@ -0,0 +1,31 @@ +--- a/Embedded/src/WDT/iwdt.c ++++ b/Embedded/src/WDT/iwdt.c +@@ -217,8 +217,7 @@ static int wdt_open(struct inode *inode, + static int wdt_release(struct inode *inode, struct file *file); + static ssize_t wdt_write(struct file *file, const char *data, + size_t count, loff_t * pos); +-static int wdt_ioctl(struct inode *inode, struct file *file, +- unsigned int cmd, unsigned long arg); ++static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + static irqreturn_t wdt_isr(int irq, void *dev_id); + static void __exit wdt_cleanup(void); + static int __init wdt_init(void); +@@ -243,7 +242,7 @@ static struct pci_device_id lpc_pci_tbl[ + static struct file_operations wdt_fops = { + owner: THIS_MODULE, + write: wdt_write, +- ioctl: wdt_ioctl, ++ unlocked_ioctl: wdt_ioctl, + open: wdt_open, + release: wdt_release, + }; +@@ -1201,8 +1200,7 @@ char *wdt_get_ioctl_string(unsigned int + * Return Value: 0 - successful, negative value - failed. + * Description: This function is used to provide IO interface. + */ +-static int wdt_ioctl(struct inode *inode, struct file *file, +- unsigned int cmd, unsigned long arg) ++static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { + u8 mode=0, scale=0, int_type=0; + u32 u_margin=0, dcount=0; diff --git a/package/system/ep80579-drivers/patches/715-3.3-1588-fixes.patch b/package/system/ep80579-drivers/patches/715-3.3-1588-fixes.patch new file mode 100644 index 0000000000..ac5dd1f2ec --- /dev/null +++ b/package/system/ep80579-drivers/patches/715-3.3-1588-fixes.patch @@ -0,0 +1,33 @@ +--- a/Embedded/src/1588/1588.c ++++ b/Embedded/src/1588/1588.c +@@ -664,8 +664,7 @@ irqreturn_t timesync_isr(int irq, void * + 0 => success + < 0 => error + ******************************************************************************/ +-int timesync_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +- unsigned long arg) ++long timesync_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + wait_queue_head_t *event = NULL; + unsigned int bytes_ret = 0; +--- a/Embedded/src/1588/1588.h ++++ b/Embedded/src/1588/1588.h +@@ -121,8 +121,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids); + // Linux functions
+ int timesync_open(struct inode *inode, struct file *filp);
+ int timesync_release(struct inode *inode, struct file *filp);
+-int timesync_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg);
++long timesync_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+ void timesync_close(void);
+ int pci_suspend(struct pci_dev *dev, pm_message_t state);
+ int pci_resume(struct pci_dev *dev);
+@@ -142,7 +141,7 @@ struct file_operations file_ops = + .owner = THIS_MODULE,
+ .open = timesync_open,
+ .release = timesync_release,
+- .ioctl = timesync_ioctl,
++ .unlocked_ioctl = timesync_ioctl,
+ };
+
+ // Linux pci operations
diff --git a/package/system/gpio-button-hotplug/Makefile b/package/system/gpio-button-hotplug/Makefile new file mode 100644 index 0000000000..adb9a45264 --- /dev/null +++ b/package/system/gpio-button-hotplug/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 2008-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=gpio-button-hotplug +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/gpio-button-hotplug + SUBMENU:=Other modules + TITLE:=Simple GPIO Button Hotplug driver + FILES:=$(PKG_BUILD_DIR)/gpio-button-hotplug.ko + AUTOLOAD:=$(call AutoLoad,30,gpio-button-hotplug) + KCONFIG:= +endef + +define KernelPackage/button-hotplug/description + Kernel module to generate GPIO button hotplug events +endef + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,gpio-button-hotplug)) diff --git a/package/system/gpio-button-hotplug/src/Makefile b/package/system/gpio-button-hotplug/src/Makefile new file mode 100644 index 0000000000..e968865631 --- /dev/null +++ b/package/system/gpio-button-hotplug/src/Makefile @@ -0,0 +1 @@ +obj-m += gpio-button-hotplug.o diff --git a/package/system/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/system/gpio-button-hotplug/src/gpio-button-hotplug.c new file mode 100644 index 0000000000..d25e70fec4 --- /dev/null +++ b/package/system/gpio-button-hotplug/src/gpio-button-hotplug.c @@ -0,0 +1,450 @@ +/* + * GPIO Button Hotplug driver + * + * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> + * + * Based on the diag.c - GPIO interface driver for Broadcom boards + * Copyright (C) 2006 Mike Baker <mbm@openwrt.org>, + * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org> + * Copyright (C) 2008 Andy Boyett <agb@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/version.h> +#include <linux/kmod.h> + +#include <linux/workqueue.h> +#include <linux/skbuff.h> +#include <linux/netlink.h> +#include <linux/kobject.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/gpio_keys.h> + +#define DRV_NAME "gpio-keys-polled" + +#define BH_SKB_SIZE 2048 + +#define PFX DRV_NAME ": " + +#undef BH_DEBUG + +#ifdef BH_DEBUG +#define BH_DBG(fmt, args...) printk(KERN_DEBUG "%s: " fmt, DRV_NAME, ##args ) +#else +#define BH_DBG(fmt, args...) do {} while (0) +#endif + +#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, DRV_NAME, ##args ) + +struct bh_priv { + unsigned long seen; +}; + +struct bh_event { + const char *name; + char *action; + unsigned long seen; + + struct sk_buff *skb; + struct work_struct work; +}; + +struct bh_map { + unsigned int code; + const char *name; +}; + +struct gpio_keys_button_data { + struct delayed_work work; + struct bh_priv bh; + int last_state; + int count; + int threshold; + int can_sleep; +}; + +extern u64 uevent_next_seqnum(void); + +#define BH_MAP(_code, _name) \ + { \ + .code = (_code), \ + .name = (_name), \ + } + +static struct bh_map button_map[] = { + BH_MAP(BTN_0, "BTN_0"), + BH_MAP(BTN_1, "BTN_1"), + BH_MAP(BTN_2, "BTN_2"), + BH_MAP(BTN_3, "BTN_3"), + BH_MAP(BTN_4, "BTN_4"), + BH_MAP(BTN_5, "BTN_5"), + BH_MAP(BTN_6, "BTN_6"), + BH_MAP(BTN_7, "BTN_7"), + BH_MAP(BTN_8, "BTN_8"), + BH_MAP(BTN_9, "BTN_9"), + BH_MAP(KEY_RESTART, "reset"), +#ifdef KEY_WPS_BUTTON + BH_MAP(KEY_WPS_BUTTON, "wps"), +#endif /* KEY_WPS_BUTTON */ +}; + +/* -------------------------------------------------------------------------*/ + +static int bh_event_add_var(struct bh_event *event, int argv, + const char *format, ...) +{ + static char buf[128]; + char *s; + va_list args; + int len; + + if (argv) + return 0; + + va_start(args, format); + len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + if (len >= sizeof(buf)) { + BH_ERR("buffer size too small\n"); + WARN_ON(1); + return -ENOMEM; + } + + s = skb_put(event->skb, len + 1); + strcpy(s, buf); + + BH_DBG("added variable '%s'\n", s); + + return 0; +} + +static int button_hotplug_fill_event(struct bh_event *event) +{ + int ret; + + ret = bh_event_add_var(event, 0, "HOME=%s", "/"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "PATH=%s", + "/sbin:/bin:/usr/sbin:/usr/bin"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button"); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "ACTION=%s", event->action); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen); + if (ret) + return ret; + + ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); + + return ret; +} + +static void button_hotplug_work(struct work_struct *work) +{ + struct bh_event *event = container_of(work, struct bh_event, work); + int ret = 0; + + event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); + if (!event->skb) + goto out_free_event; + + ret = bh_event_add_var(event, 0, "%s@", event->action); + if (ret) + goto out_free_skb; + + ret = button_hotplug_fill_event(event); + if (ret) + goto out_free_skb; + + NETLINK_CB(event->skb).dst_group = 1; + broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); + + out_free_skb: + if (ret) { + BH_ERR("work error %d\n", ret); + kfree_skb(event->skb); + } + out_free_event: + kfree(event); +} + +static int button_hotplug_create_event(const char *name, unsigned long seen, + int pressed) +{ + struct bh_event *event; + + BH_DBG("create event, name=%s, seen=%lu, pressed=%d\n", + name, seen, pressed); + + event = kzalloc(sizeof(*event), GFP_KERNEL); + if (!event) + return -ENOMEM; + + event->name = name; + event->seen = seen; + event->action = pressed ? "pressed" : "released"; + + INIT_WORK(&event->work, (void *)(void *)button_hotplug_work); + schedule_work(&event->work); + + return 0; +} + +/* -------------------------------------------------------------------------*/ + +#ifdef CONFIG_HOTPLUG +static int button_get_index(unsigned int code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(button_map); i++) + if (button_map[i].code == code) + return i; + + return -1; +} +static void button_hotplug_event(struct gpio_keys_button_data *data, + unsigned int type, unsigned int code, int value) +{ + struct bh_priv *priv = &data->bh; + unsigned long seen = jiffies; + int btn; + + BH_DBG("event type=%u, code=%u, value=%d\n", type, code, value); + + if (type != EV_KEY) + return; + + btn = button_get_index(code); + if (btn < 0) + return; + + button_hotplug_create_event(button_map[btn].name, + (seen - priv->seen) / HZ, value); + priv->seen = seen; +} +#else +static void button_hotplug_event(struct gpio_keys_button_data *data, + unsigned int type, unsigned int code, int value) +{ +} +#endif /* CONFIG_HOTPLUG */ + +struct gpio_keys_polled_dev { + struct delayed_work work; + + struct device *dev; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button_data data[0]; +}; + +static void gpio_keys_polled_check_state(struct gpio_keys_button *button, + struct gpio_keys_button_data *bdata) +{ + int state; + + if (bdata->can_sleep) + state = !!gpio_get_value_cansleep(button->gpio); + else + state = !!gpio_get_value(button->gpio); + + state = !!(state ^ button->active_low); + if (state != bdata->last_state) { + unsigned int type = button->type ?: EV_KEY; + + button_hotplug_event(bdata, type, button->code, state); + bdata->count = 0; + bdata->last_state = state; + } +} + +static void gpio_keys_polled_queue_work(struct gpio_keys_polled_dev *bdev) +{ + struct gpio_keys_platform_data *pdata = bdev->pdata; + unsigned long delay = msecs_to_jiffies(pdata->poll_interval); + + if (delay >= HZ) + delay = round_jiffies_relative(delay); + schedule_delayed_work(&bdev->work, delay); +} + +static void gpio_keys_polled_poll(struct work_struct *work) +{ + struct gpio_keys_polled_dev *bdev = + container_of(work, struct gpio_keys_polled_dev, work.work); + struct gpio_keys_platform_data *pdata = bdev->pdata; + int i; + + for (i = 0; i < bdev->pdata->nbuttons; i++) { + struct gpio_keys_button_data *bdata = &bdev->data[i]; + + if (bdata->count < bdata->threshold) + bdata->count++; + else + gpio_keys_polled_check_state(&pdata->buttons[i], bdata); + } + gpio_keys_polled_queue_work(bdev); +} + +static void __devinit gpio_keys_polled_open(struct gpio_keys_polled_dev *bdev) +{ + struct gpio_keys_platform_data *pdata = bdev->pdata; + int i; + + if (pdata->enable) + pdata->enable(bdev->dev); + + /* report initial state of the buttons */ + for (i = 0; i < pdata->nbuttons; i++) + gpio_keys_polled_check_state(&pdata->buttons[i], &bdev->data[i]); + + gpio_keys_polled_queue_work(bdev); +} + +static void __devexit gpio_keys_polled_close(struct gpio_keys_polled_dev *bdev) +{ + struct gpio_keys_platform_data *pdata = bdev->pdata; + + cancel_delayed_work_sync(&bdev->work); + + if (pdata->disable) + pdata->disable(bdev->dev); +} + +static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) +{ + struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct gpio_keys_polled_dev *bdev; + int error; + int i; + + if (!pdata || !pdata->poll_interval) + return -EINVAL; + + bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + + pdata->nbuttons * sizeof(struct gpio_keys_button_data), + GFP_KERNEL); + if (!bdev) { + dev_err(dev, "no memory for private data\n"); + return -ENOMEM; + } + + for (i = 0; i < pdata->nbuttons; i++) { + struct gpio_keys_button *button = &pdata->buttons[i]; + struct gpio_keys_button_data *bdata = &bdev->data[i]; + unsigned int gpio = button->gpio; + + if (button->wakeup) { + dev_err(dev, DRV_NAME " does not support wakeup\n"); + error = -EINVAL; + goto err_free_gpio; + } + + error = gpio_request(gpio, + button->desc ? button->desc : DRV_NAME); + if (error) { + dev_err(dev, "unable to claim gpio %u, err=%d\n", + gpio, error); + goto err_free_gpio; + } + + error = gpio_direction_input(gpio); + if (error) { + dev_err(dev, + "unable to set direction on gpio %u, err=%d\n", + gpio, error); + goto err_free_gpio; + } + + bdata->can_sleep = gpio_cansleep(gpio); + bdata->last_state = 0; + bdata->threshold = DIV_ROUND_UP(button->debounce_interval, + pdata->poll_interval); + } + + bdev->dev = &pdev->dev; + bdev->pdata = pdata; + platform_set_drvdata(pdev, bdev); + + INIT_DELAYED_WORK(&bdev->work, gpio_keys_polled_poll); + + gpio_keys_polled_open(bdev); + + return 0; + +err_free_gpio: + while (--i >= 0) + gpio_free(pdata->buttons[i].gpio); + + kfree(bdev); + platform_set_drvdata(pdev, NULL); + + return error; +} + +static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) +{ + struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); + struct gpio_keys_platform_data *pdata = bdev->pdata; + int i = pdata->nbuttons; + + gpio_keys_polled_close(bdev); + + while (--i >= 0) + gpio_free(pdata->buttons[i].gpio); + + kfree(bdev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver gpio_keys_polled_driver = { + .probe = gpio_keys_polled_probe, + .remove = __devexit_p(gpio_keys_polled_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init gpio_keys_polled_init(void) +{ + return platform_driver_register(&gpio_keys_polled_driver); +} + +static void __exit gpio_keys_polled_exit(void) +{ + platform_driver_unregister(&gpio_keys_polled_driver); +} + +module_init(gpio_keys_polled_init); +module_exit(gpio_keys_polled_exit); + +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); +MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); +MODULE_DESCRIPTION("Polled GPIO Buttons hotplug driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/package/system/hostap-driver/Makefile b/package/system/hostap-driver/Makefile new file mode 100644 index 0000000000..d08fd9c0a5 --- /dev/null +++ b/package/system/hostap-driver/Makefile @@ -0,0 +1,117 @@ +# +# Copyright (C) 2006-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=hostap-driver +PKG_VERSION:=0.4.9 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://hostap.epitest.fi/releases/ +PKG_MD5SUM:=c7534dc040ab90218257a78488ecd378 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/hostap/Default + VERSION:=$(LINUX_VERSION)-$(BOARD)-$(PKG_RELEASE) + SUBMENU:=Wireless Drivers + URL:=http://hostap.epitest.fi/ +endef + +define KernelPackage/hostap/Default/description + Host AP is a driver for 802.11b wireless cards based on Intersil + Prism2/2.5/3 chipset. It supports so called Host AP mode that allows the + card to act as an IEEE 802.11 access point. +endef + + +define KernelPackage/hostap +$(call KernelPackage/hostap/Default) + TITLE:=Host AP support for Prism2/2.5/3 + DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-lib80211 +wireless-tools + KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y + FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap.ko + AUTOLOAD:=$(call AutoLoad,60,hostap) +endef + +define KernelPackage/hostap/description +$(call KernelPackage/hostap/Default/description) + This package contains the base Host AP driver code that is shared by + different hardware models. You will also need to enable support for + PLX/PCI/CS version of the driver to actually use the driver. +endef + + +define KernelPackage/hostap-cs +$(call KernelPackage/hostap/Default) + TITLE:=Host AP driver for PCMCIA adaptors + DEPENDS:=@PCMCIA_SUPPORT +kmod-hostap +kmod-pcmcia-core + KCONFIG:=CONFIG_HOSTAP_CS + FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_cs.ko + AUTOLOAD:=$(call AutoLoad,60,hostap_cs) +endef + +define KernelPackage/hostap-cs/description +$(call KernelPackage/hostap/Default/description) + This package contains the Host AP driver for Prism2/2.5/3 PC cards. +endef + + +define KernelPackage/hostap-pci +$(call KernelPackage/hostap/Default) + TITLE:=Host AP driver for PCI adaptors + DEPENDS:=@PCI_SUPPORT +kmod-hostap + KCONFIG:=CONFIG_HOSTAP_PCI + FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_pci.ko + AUTOLOAD:=$(call AutoLoad,60,hostap_pci) +endef + +define KernelPackage/hostap-pci/description +$(call KernelPackage/hostap/Default/description) + This package contains the Host AP driver for Prism2.5 PCI adaptors. +endef + + +define KernelPackage/hostap-plx +$(call KernelPackage/hostap/Default) + TITLE:=Host AP driver for PLX9052 based PCI adaptors + DEPENDS:=@PCI_SUPPORT +kmod-hostap + KCONFIG:=CONFIG_HOSTAP_PLX + FILES:=$(LINUX_DIR)/drivers/net/wireless/hostap/hostap_plx.ko + AUTOLOAD:=$(call AutoLoad,60,hostap_plx) +endef + +define KernelPackage/hostap-plx/description +$(call KernelPackage/hostap/Default/description) + This package contains the Host AP driver for Prism2/2.5/3 in PLX9052 + based PCI adaptors. +endef + + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Configure + +endef + +define Build/Compile + +endef + +define KernelPackage/hostap/install + $(INSTALL_DIR) $(1)/lib/wifi + $(INSTALL_DATA) ./files/lib/wifi/hostap.sh $(1)/lib/wifi +endef + +$(eval $(call KernelPackage,hostap)) +$(eval $(call KernelPackage,hostap-cs)) +$(eval $(call KernelPackage,hostap-pci)) +$(eval $(call KernelPackage,hostap-plx)) diff --git a/package/system/hostap-driver/files/lib/wifi/hostap.sh b/package/system/hostap-driver/files/lib/wifi/hostap.sh new file mode 100755 index 0000000000..62d2e7e472 --- /dev/null +++ b/package/system/hostap-driver/files/lib/wifi/hostap.sh @@ -0,0 +1,270 @@ +#!/bin/sh +append DRIVERS "prism2" + +find_prism2_phy() { + local device="$1" + + local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')" + config_get phy "$device" phy + [ -z "$phy" -a -n "$macaddr" ] && { + cd /proc/net/hostap + for phy in $(ls -d wlan* 2>&-); do + [ "$macaddr" = "$(cat /sys/class/net/${phy}/address)" ] || continue + config_set "$device" phy "$phy" + break + done + config_get phy "$device" phy + } + [ -n "$phy" -a -d "/proc/net/hostap/$phy" ] || { + echo "phy for wifi device $1 not found" + return 1 + } + [ -z "$macaddr" ] && { + config_set "$device" macaddr "$(cat /sys/class/net/${phy}/address)" + } + return 0 +} + +scan_prism2() { + local device="$1" + local mainvif + local wds + + [ ${device%[0-9]} = "wlan" ] && config_set "$device" phy "$device" || find_prism2_phy "$device" || { + config_unset "$device" vifs + return 0 + } + config_get phy "$device" phy + + config_get vifs "$device" vifs + local _c=0 + for vif in $vifs; do + config_get_bool disabled "$vif" disabled 0 + [ $disabled = 0 ] || continue + + config_get mode "$vif" mode + case "$mode" in + adhoc|sta|ap|monitor) + # Only one vif is allowed on AP, station, Ad-hoc or monitor mode + [ -z "$mainvif" ] && { + mainvif="$vif" + config_set "$vif" ifname "$phy" + } + ;; + wds) + config_get ssid "$vif" ssid + [ -z "$ssid" ] && continue + config_set "$vif" ifname "${phy}wds${_c}" + _c=$(($_c + 1)) + addr="$ssid" + ${addr:+append wds "$vif"} + ;; + *) echo "$device($vif): Invalid mode, ignored."; continue;; + esac + done + config_set "$device" vifs "${mainvif:+$mainvif }${wds:+$wds}" +} + +disable_prism2() ( + local device="$1" + + find_prism2_phy "$device" || return 0 + config_get phy "$device" phy + + set_wifi_down "$device" + + include /lib/network + while read line < /proc/net/hostap/${phy}/wds; do + set $line + [ -f "/var/run/wifi-${1}.pid" ] && + kill "$(cat "/var/run/wifi-${1}.pid")" + ifconfig "$1" down + unbridge "$1" + iwpriv "$phy" wds_del "$2" + done + unbridge "$phy" + return 0 +) + +enable_prism2() { + local device="$1" + + find_prism2_phy "$device" || return 0 + config_get phy "$device" phy + + config_get rxantenna "$device" rxantenna + config_get txantenna "$device" txantenna + config_get_bool diversity "$device" diversity + [ -n "$diversity" ] && { + rxantenna="1" + txantenna="1" + } + [ -n "$rxantenna" ] && iwpriv "$phy" antsel_rx "$rxantenna" + [ -n "$txantenna" ] && iwpriv "$phy" antsel_tx "$txantenna" + + config_get channel "$device" channel + [ -n "$channel" ] && iwconfig "$phy" channel "$channel" >/dev/null 2>/dev/null + + config_get txpower "$device" txpower + [ -n "$txpower" ] && iwconfig "$phy" txpower "${txpower%%.*}" + + config_get vifs "$device" vifs + local first=1 + for vif in $vifs; do + config_get ifname "$vif" ifname + config_get ssid "$vif" ssid + config_get mode "$vif" mode + + [ "$mode" = "wds" ] || iwconfig "$phy" essid ${ssid:+-- }"${ssid:-any}" + + case "$mode" in + sta) + iwconfig "$phy" mode managed + config_get addr "$device" bssid + [ -z "$addr" ] || { + iwconfig "$phy" ap "$addr" + } + ;; + ap) iwconfig "$phy" mode master;; + wds) iwpriv "$phy" wds_add "$ssid";; + adhoc) iwconfig "$phy" mode ad-hoc;; + *) iwconfig "$phy" mode "$mode";; + esac + + [ "$first" = 1 ] && { + config_get rate "$vif" rate + [ -n "$rate" ] && iwconfig "$phy" rate "${rate%%.*}" + + config_get_bool hidden "$vif" hidden 0 + iwpriv "$phy" enh_sec "$hidden" + + config_get frag "$vif" frag + [ -n "$frag" ] && iwconfig "$phy" frag "${frag%%.*}" + + config_get rts "$vif" rts + [ -n "$rts" ] && iwconfig "$phy" rts "${rts%%.*}" + + config_get maclist "$vif" maclist + [ -n "$maclist" ] && { + # flush MAC list + iwpriv "$phy" maccmd 3 + for mac in $maclist; do + iwpriv "$phy" addmac "$mac" + done + } + config_get macpolicy "$vif" macpolicy + case "$macpolicy" in + allow) + iwpriv "$phy" maccmd 2 + ;; + deny) + iwpriv "$phy" maccmd 1 + ;; + *) + # default deny policy if mac list exists + [ -n "$maclist" ] && iwpriv "$phy" maccmd 1 + ;; + esac + # kick all stations if we have policy explicitly set + [ -n "$macpolicy" ] && iwpriv "$phy" maccmd 4 + } + + config_get enc "$vif" encryption + case "$enc" in + WEP|wep) + for idx in 1 2 3 4; do + config_get key "$vif" "key${idx}" + iwconfig "$ifname" enc "[$idx]" "${key:-off}" + done + config_get key "$vif" key + key="${key:-1}" + case "$key" in + [1234]) iwconfig "$ifname" enc "[$key]";; + *) iwconfig "$ifname" enc "$key";; + esac + ;; + psk*|wpa*) + start_hostapd=1 + config_get key "$vif" key + ;; + esac + + local net_cfg bridge + net_cfg="$(find_net_config "$vif")" + [ -z "$net_cfg" ] || { + bridge="$(bridge_interface "$net_cfg")" + config_set "$vif" bridge "$bridge" + start_net "$ifname" "$net_cfg" + } + set_wifi_up "$vif" "$ifname" + + case "$mode" in + ap) + if [ -n "$start_hostapd" ] && eval "type hostapd_setup_vif" 2>/dev/null >/dev/null; then + hostapd_setup_vif "$vif" hostap || { + echo "enable_prism2($device): Failed to set up hostapd for interface $ifname" >&2 + # make sure this wifi interface won't accidentally stay open without encryption + ifconfig "$ifname" down + continue + } + fi + ;; + wds|sta) + if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then + wpa_supplicant_setup_vif "$vif" wext || { + echo "enable_prism2($device): Failed to set up wpa_supplicant for interface $ifname" >&2 + ifconfig "$ifname" down + continue + } + fi + ;; + esac + first=0 + done + +} + +check_prism2_device() { + [ ${1%[0-9]} = "wlan" ] && config_set "$1" phy "$1" + config_get phy "$1" phy + [ -z "$phy" ] && { + find_prism2_phy "$1" >/dev/null || return 0 + config_get phy "$1" phy + } + [ "$phy" = "$dev" ] && found=1 +} + +detect_prism2() { + devidx=0 + config_load wireless + while :; do + config_get type "radio$devidx" type + [ -n "$type" ] || break + devidx=$(($devidx + 1)) + done + cd /proc/net/hostap + [ -d wlan* ] || return + for dev in $(ls -d wlan* 2>&-); do + found=0 + config_foreach check_prism2_device wifi-device + [ "$found" -gt 0 ] && continue + cat <<EOF +config wifi-device radio$devidx + option type prism2 + option channel 11 + option macaddr $(cat /sys/class/net/${dev}/address) + + # REMOVE THIS LINE TO ENABLE WIFI: + option disabled 1 + +config wifi-iface + option device radio$devidx + option network lan + option mode ap + option ssid OpenWrt + option encryption none + +EOF + devidx=$(($devidx + 1)) + done +} diff --git a/package/system/hostap-driver/patches/001-fix-txpower.patch b/package/system/hostap-driver/patches/001-fix-txpower.patch new file mode 100644 index 0000000000..94ca344943 --- /dev/null +++ b/package/system/hostap-driver/patches/001-fix-txpower.patch @@ -0,0 +1,175 @@ +diff -Naur hostap-driver-0.3.7/driver/modules/hostap.c hostap-driver-0.3.7-patched/driver/modules/hostap.c +--- hostap-driver-0.3.7/driver/modules/hostap.c 2004-08-28 06:26:46.000000000 +0300 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap.c 2005-04-20 17:20:56.000000000 +0300 +@@ -1164,6 +1164,36 @@ + return ret; + } + ++/* BUG FIX: Restore power setting value when lost due to F/W bug */ ++ ++int hostap_restore_power(struct net_device *dev) ++{ ++ struct hostap_interface *iface = dev->priv; ++ local_info_t *local = iface->local; ++ ++ u16 val; ++ int ret = 0; ++ ++ if (local->txpower_type == PRISM2_TXPOWER_OFF) { ++ val = 0xff; /* use all standby and sleep modes */ ++ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, ++ HFA386X_CR_A_D_TEST_MODES2, ++ &val, NULL); ++ } ++ ++#ifdef RAW_TXPOWER_SETTING ++ if (local->txpower_type == PRISM2_TXPOWER_FIXED) { ++ val = HFA384X_TEST_CFG_BIT_ALC; ++ local->func->cmd(dev, HFA384X_CMDCODE_TEST | ++ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL); ++ val = prism2_txpower_dBm_to_hfa386x(local->txpower); ++ ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, ++ HFA386X_CR_MANUAL_TX_POWER, &val, NULL)); ++ } ++#endif /* RAW_TXPOWER_SETTING */ ++ return (ret ? -EOPNOTSUPP : 0); ++} ++ + + struct proc_dir_entry *hostap_proc; + +@@ -1214,6 +1244,7 @@ + EXPORT_SYMBOL(hostap_set_hostapd_sta); + EXPORT_SYMBOL(hostap_add_interface); + EXPORT_SYMBOL(hostap_remove_interface); ++EXPORT_SYMBOL(hostap_restore_power); + EXPORT_SYMBOL(prism2_update_comms_qual); + + module_init(hostap_init); +diff -Naur hostap-driver-0.3.7/driver/modules/hostap.h hostap-driver-0.3.7-patched/driver/modules/hostap.h +--- hostap-driver-0.3.7/driver/modules/hostap.h 2003-11-30 04:14:26.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap.h 2005-04-20 17:21:23.000000000 +0300 +@@ -36,6 +36,7 @@ + const char *prefix, const char *name); + void hostap_remove_interface(struct net_device *dev, int rtnl_locked, + int remove_from_list); ++int hostap_restore_power(struct net_device *dev); + int prism2_update_comms_qual(struct net_device *dev); + int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u8 stype, + u8 *body, size_t bodylen); +diff -Naur hostap-driver-0.3.7/driver/modules/hostap_ap.c hostap-driver-0.3.7-patched/driver/modules/hostap_ap.c +--- hostap-driver-0.3.7/driver/modules/hostap_ap.c 2005-01-24 04:52:00.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap_ap.c 2005-04-21 20:06:12.000000000 +0300 +@@ -2346,13 +2346,13 @@ + addr[count].sa_family = ARPHRD_ETHER; + memcpy(addr[count].sa_data, sta->addr, ETH_ALEN); + if (sta->last_rx_silence == 0) +- qual[count].qual = sta->last_rx_signal < 27 ? +- 0 : (sta->last_rx_signal - 27) * 92 / 127; ++ qual[count].qual = (sta->last_rx_signal - 156) == 0 ? ++ 0 : (sta->last_rx_signal - 156) * 92 / 64; + else +- qual[count].qual = sta->last_rx_signal - +- sta->last_rx_silence - 35; +- qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); +- qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); ++ qual[count].qual = (sta->last_rx_signal - ++ sta->last_rx_silence) * 92 / 64; ++ qual[count].level = sta->last_rx_signal; ++ qual[count].noise = sta->last_rx_silence; + qual[count].updated = sta->last_rx_updated; + + sta->last_rx_updated = 0; +@@ -2413,13 +2413,13 @@ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + if (sta->last_rx_silence == 0) +- iwe.u.qual.qual = sta->last_rx_signal < 27 ? +- 0 : (sta->last_rx_signal - 27) * 92 / 127; ++ iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ? ++ 0 : (sta->last_rx_signal - 156) * 92 / 64; + else +- iwe.u.qual.qual = sta->last_rx_signal - +- sta->last_rx_silence - 35; +- iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); +- iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); ++ iwe.u.qual.qual = (sta->last_rx_signal - ++ sta->last_rx_silence) * 92 / 64; ++ iwe.u.qual.level = sta->last_rx_signal; ++ iwe.u.qual.noise = sta->last_rx_silence; + iwe.u.qual.updated = sta->last_rx_updated; + iwe.len = IW_EV_QUAL_LEN; + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, +diff -Naur hostap-driver-0.3.7/driver/modules/hostap_config.h hostap-driver-0.3.7-patched/driver/modules/hostap_config.h +--- hostap-driver-0.3.7/driver/modules/hostap_config.h 2005-02-12 18:12:56.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap_config.h 2005-04-20 17:25:23.000000000 +0300 +@@ -94,6 +94,12 @@ + */ + /* #define PRISM2_NO_STATION_MODES */ + ++/* Enable TX power Setting functions ++ * (min att = -128 , max att = 127) ++ */ ++ ++#define RAW_TXPOWER_SETTING ++ + /* Use Linux crypto API instead of own encryption implementation whenever + * possible. */ + /* #define HOSTAP_USE_CRYPTO_API */ +diff -Naur hostap-driver-0.3.7/driver/modules/hostap_hw.c hostap-driver-0.3.7-patched/driver/modules/hostap_hw.c +--- hostap-driver-0.3.7/driver/modules/hostap_hw.c 2005-02-05 09:20:09.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap_hw.c 2005-04-20 17:25:55.000000000 +0300 +@@ -1039,6 +1039,7 @@ + dev->name, local->fragm_threshold); + } + ++ hostap_restore_power(dev); + return res; + } + +diff -Naur hostap-driver-0.3.7/driver/modules/hostap_info.c hostap-driver-0.3.7-patched/driver/modules/hostap_info.c +--- hostap-driver-0.3.7/driver/modules/hostap_info.c 2004-02-29 20:05:44.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap_info.c 2005-04-20 17:26:36.000000000 +0300 +@@ -418,6 +418,11 @@ + } + + /* Get BSSID if we have a valid AP address */ ++ ++ if ( val == HFA384X_LINKSTATUS_CONNECTED || ++ val == HFA384X_LINKSTATUS_DISCONNECTED ) ++ hostap_restore_power(local->dev); ++ + if (connected) { + netif_carrier_on(local->dev); + netif_carrier_on(local->ddev); +diff -Naur hostap-driver-0.3.7/driver/modules/hostap_ioctl.c hostap-driver-0.3.7-patched/driver/modules/hostap_ioctl.c +--- hostap-driver-0.3.7/driver/modules/hostap_ioctl.c 2004-11-22 08:03:05.000000000 +0200 ++++ hostap-driver-0.3.7-patched/driver/modules/hostap_ioctl.c 2005-04-20 17:42:41.000000000 +0300 +@@ -1453,23 +1453,20 @@ + val = 255; + + tmp = val; +- tmp >>= 2; + +- return -12 - tmp; ++ return tmp; + } + + static u16 prism2_txpower_dBm_to_hfa386x(int val) + { + signed char tmp; + +- if (val > 20) +- return 128; +- else if (val < -43) ++ if (val > 127) + return 127; ++ else if (val < -128) ++ return 128; + + tmp = val; +- tmp = -12 - tmp; +- tmp <<= 2; + + return (unsigned char) tmp; + } diff --git a/package/system/i2c-gpio-custom/Makefile b/package/system/i2c-gpio-custom/Makefile new file mode 100644 index 0000000000..8585a5ab57 --- /dev/null +++ b/package/system/i2c-gpio-custom/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=i2c-gpio-custom +PKG_RELEASE:=2 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/i2c-gpio-custom + SUBMENU:=I2C support + TITLE:=Custom GPIO-based I2C device + DEPENDS:=@GPIO_SUPPORT +kmod-i2c-core +kmod-i2c-gpio + FILES:=$(PKG_BUILD_DIR)/i2c-gpio-custom.ko + KCONFIG:= +endef + +define KernelPackage/i2c-gpio-custom/description + Kernel module for register a custom i2c-gpio platform device. +endef + +EXTRA_KCONFIG:= \ + CONFIG_I2C_GPIO_CUSTOM=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,i2c-gpio-custom)) diff --git a/package/system/i2c-gpio-custom/src/Kconfig b/package/system/i2c-gpio-custom/src/Kconfig new file mode 100644 index 0000000000..e2e3a68d92 --- /dev/null +++ b/package/system/i2c-gpio-custom/src/Kconfig @@ -0,0 +1,10 @@ +config I2C_GPIO_CUSTOM + tristate "Custom GPIO-based I2C driver" + depends on GENERIC_GPIO + select I2C_GPIO + help + This is an I2C driver to register 1 to 4 custom I2C buses using + GPIO lines. + + This support is also available as a module. If so, the module + will be called i2c-gpio-custom. diff --git a/package/system/i2c-gpio-custom/src/Makefile b/package/system/i2c-gpio-custom/src/Makefile new file mode 100644 index 0000000000..dcb2e2abe2 --- /dev/null +++ b/package/system/i2c-gpio-custom/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_I2C_GPIO_CUSTOM} += i2c-gpio-custom.o
\ No newline at end of file diff --git a/package/system/i2c-gpio-custom/src/i2c-gpio-custom.c b/package/system/i2c-gpio-custom/src/i2c-gpio-custom.c new file mode 100644 index 0000000000..76ab5f39cc --- /dev/null +++ b/package/system/i2c-gpio-custom/src/i2c-gpio-custom.c @@ -0,0 +1,198 @@ +/* + * Custom GPIO-based I2C driver + * + * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * --------------------------------------------------------------------------- + * + * The behaviour of this driver can be altered by setting some parameters + * from the insmod command line. + * + * The following parameters are adjustable: + * + * bus0 These four arguments can be arrays of + * bus1 1-8 unsigned integers as follows: + * bus2 + * bus3 <id>,<sda>,<scl>,<udelay>,<timeout>,<sda_od>,<scl_od>,<scl_oo> + * + * where: + * + * <id> ID to used as device_id for the corresponding bus (required) + * <sda> GPIO pin ID to used for SDA (required) + * <scl> GPIO pin ID to used for SCL (required) + * <udelay> signal toggle delay. + * <timeout> clock stretching timeout. + * <sda_od> SDA is configured as open drain. + * <scl_od> SCL is configured as open drain. + * <scl_oo> SCL output drivers cannot be turned off. + * + * See include/i2c-gpio.h for more information about the parameters. + * + * If this driver is built into the kernel, you can use the following kernel + * command line parameters, with the same values as the corresponding module + * parameters listed above: + * + * i2c-gpio-custom.bus0 + * i2c-gpio-custom.bus1 + * i2c-gpio-custom.bus2 + * i2c-gpio-custom.bus3 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <linux/i2c-gpio.h> + +#define DRV_NAME "i2c-gpio-custom" +#define DRV_DESC "Custom GPIO-based I2C driver" +#define DRV_VERSION "0.1.1" + +#define PFX DRV_NAME ": " + +#define BUS_PARAM_ID 0 +#define BUS_PARAM_SDA 1 +#define BUS_PARAM_SCL 2 +#define BUS_PARAM_UDELAY 3 +#define BUS_PARAM_TIMEOUT 4 +#define BUS_PARAM_SDA_OD 5 +#define BUS_PARAM_SCL_OD 6 +#define BUS_PARAM_SCL_OO 7 + +#define BUS_PARAM_REQUIRED 3 +#define BUS_PARAM_COUNT 8 +#define BUS_COUNT_MAX 4 + +static unsigned int bus0[BUS_PARAM_COUNT] __initdata; +static unsigned int bus1[BUS_PARAM_COUNT] __initdata; +static unsigned int bus2[BUS_PARAM_COUNT] __initdata; +static unsigned int bus3[BUS_PARAM_COUNT] __initdata; + +static unsigned int bus_nump[BUS_COUNT_MAX] __initdata; + +#define BUS_PARM_DESC \ + " config -> id,sda,scl[,udelay,timeout,sda_od,scl_od,scl_oo]" + +module_param_array(bus0, uint, &bus_nump[0], 0); +MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC); +module_param_array(bus1, uint, &bus_nump[1], 0); +MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC); +module_param_array(bus2, uint, &bus_nump[2], 0); +MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC); +module_param_array(bus3, uint, &bus_nump[3], 0); +MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC); + +static struct platform_device *devices[BUS_COUNT_MAX]; +static unsigned int nr_devices; + +static void i2c_gpio_custom_cleanup(void) +{ + int i; + + for (i = 0; i < nr_devices; i++) + if (devices[i]) + platform_device_put(devices[i]); +} + +static int __init i2c_gpio_custom_add_one(unsigned int id, unsigned int *params) +{ + struct platform_device *pdev; + struct i2c_gpio_platform_data pdata; + int err; + + if (!bus_nump[id]) + return 0; + + if (bus_nump[id] < BUS_PARAM_REQUIRED) { + printk(KERN_ERR PFX "not enough parameters for bus%d\n", id); + err = -EINVAL; + goto err; + } + + pdev = platform_device_alloc("i2c-gpio", params[BUS_PARAM_ID]); + if (!pdev) { + err = -ENOMEM; + goto err; + } + + pdata.sda_pin = params[BUS_PARAM_SDA]; + pdata.scl_pin = params[BUS_PARAM_SCL]; + pdata.udelay = params[BUS_PARAM_UDELAY]; + pdata.timeout = params[BUS_PARAM_TIMEOUT]; + pdata.sda_is_open_drain = params[BUS_PARAM_SDA_OD] != 0; + pdata.scl_is_open_drain = params[BUS_PARAM_SCL_OD] != 0; + pdata.scl_is_output_only = params[BUS_PARAM_SCL_OO] != 0; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put; + + err = platform_device_add(pdev); + if (err) + goto err_put; + + devices[nr_devices++] = pdev; + return 0; + +err_put: + platform_device_put(pdev); +err: + return err; +} + +static int __init i2c_gpio_custom_probe(void) +{ + int err; + + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); + + err = i2c_gpio_custom_add_one(0, bus0); + if (err) goto err; + + err = i2c_gpio_custom_add_one(1, bus1); + if (err) goto err; + + err = i2c_gpio_custom_add_one(2, bus2); + if (err) goto err; + + err = i2c_gpio_custom_add_one(3, bus3); + if (err) goto err; + + if (!nr_devices) { + printk(KERN_ERR PFX "no bus parameter(s) specified\n"); + err = -ENODEV; + goto err; + } + + return 0; + +err: + i2c_gpio_custom_cleanup(); + return err; +} + +#ifdef MODULE +static int __init i2c_gpio_custom_init(void) +{ + return i2c_gpio_custom_probe(); +} +module_init(i2c_gpio_custom_init); + +static void __exit i2c_gpio_custom_exit(void) +{ + i2c_gpio_custom_cleanup(); +} +module_exit(i2c_gpio_custom_exit); +#else +subsys_initcall(i2c_gpio_custom_probe); +#endif /* MODULE*/ + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org >"); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); diff --git a/package/system/ixp4xx-microcode/Makefile b/package/system/ixp4xx-microcode/Makefile new file mode 100644 index 0000000000..52b44f35f9 --- /dev/null +++ b/package/system/ixp4xx-microcode/Makefile @@ -0,0 +1,57 @@ +# +# Copyright (C) 2007 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=ixp4xx-microcode +PKG_VERSION:=2.4 +PKG_RELEASE:=2 + +PKG_SOURCE:=IPL_ixp400NpeLibraryWithCrypto-2_4.zip +PKG_SOURCE_URL:=http://downloads.openwrt.org/sources +PKG_MD5SUM:=dd5f6482e625ecb334469958bcd54b37 + +include $(INCLUDE_DIR)/package.mk + +define Package/ixp4xx-microcode + SECTION:=net + CATEGORY:=Network + TITLE:=Microcode for the IXP4xx network engines + DEPENDS:=@TARGET_ixp4xx +endef + +define Package/ixp4xx-microcode/description + This package contains the microcode needed to use the network engines in IXP4xx CPUs +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + unzip -d $(PKG_BUILD_DIR)/ $(DL_DIR)/$(PKG_SOURCE) + mv $(PKG_BUILD_DIR)/ixp400_xscale_sw/src/npeDl/IxNpeMicrocode.c $(PKG_BUILD_DIR)/ + rm -rf $(PKG_BUILD_DIR)/ixp400_xscale_sw + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + (cd $(PKG_BUILD_DIR); \ + $(HOSTCC) -Wall -I$(STAGING_DIR_HOST)/include IxNpeMicrocode.c -o IxNpeMicrocode; \ + ./IxNpeMicrocode -be \ + ) +endef + +define Package/ixp4xx-microcode/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DIR) $(1)/usr/share/doc + $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-A $(1)/lib/firmware/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-A-HSS $(1)/lib/firmware/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-B $(1)/lib/firmware/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/NPE-C $(1)/lib/firmware/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE.IPL $(1)/usr/share/doc/ +endef + +$(eval $(call BuildPackage,ixp4xx-microcode)) diff --git a/package/system/ixp4xx-microcode/src/IxNpeMicrocode.h b/package/system/ixp4xx-microcode/src/IxNpeMicrocode.h new file mode 100644 index 0000000000..4a843db104 --- /dev/null +++ b/package/system/ixp4xx-microcode/src/IxNpeMicrocode.h @@ -0,0 +1,148 @@ +/* + * IxNpeMicrocode.h - Headerfile for compiling the Intel microcode C file + * + * Copyright (C) 2006 Christian Hohnstaedt <chohnstaedt@innominate.com> + * + * This file is released under the GPLv2 + * + * + * compile with + * + * gcc -Wall IxNpeMicrocode.c -o IxNpeMicrocode + * + * Executing the resulting binary on your build-host creates the + * "NPE-[ABC].xxxxxxxx" files containing the selected microcode + * + * fetch the IxNpeMicrocode.c from the Intel Access Library. + * It will include this header. + * + * select Images for every NPE from the following + * (used C++ comments for easy uncommenting ....) + */ + +// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEA_HSS_TSLOT_SWITCH +#define IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV +// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS +// #define IX_NPEDL_NPEIMAGE_NPEA_ETH_LEARN_FILTER_SPAN_FIREWALL +#define IX_NPEDL_NPEIMAGE_NPEA_HSS_2_PORT +// #define IX_NPEDL_NPEIMAGE_NPEA_DMA +// #define IX_NPEDL_NPEIMAGE_NPEA_ATM_MPHY_12_PORT +// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0_ATM_MPHY_1_PORT +// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0_ATM_SPHY_1_PORT +// #define IX_NPEDL_NPEIMAGE_NPEA_HSS0 +// #define IX_NPEDL_NPEIMAGE_NPEA_WEP + + +// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEB_DMA +#define IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV +// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS +// #define IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL + + +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_MASK_FIREWALL_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB +// #define IX_NPEDL_NPEIMAGE_NPEC_DMA +// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_ETH_LEARN_FILTER_SPAN +// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_ETH_LEARN_FILTER_FIREWALL +#define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_CCM_ETH +// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_AES_CCM_EXTSHA_ETH +// #define IX_NPEDL_NPEIMAGE_NPEC_CRYPTO_ETH_LEARN_FILTER_SPAN_FIREWALL +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_FIREWALL_VLAN_QOS_HDR_CONV +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS +// #define IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL + + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <endian.h> +#include <byteswap.h> +#include <string.h> + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define to_le32(x) (x) +#define to_be32(x) bswap_32(x) +#else +#define to_be32(x) (x) +#define to_le32(x) bswap_32(x) +#endif + +struct dl_image { + unsigned magic; + unsigned id; + unsigned size; + unsigned data[0]; +}; + +const unsigned IxNpeMicrocode_array[]; + +int main(int argc, char *argv[]) +{ + struct dl_image *image = (struct dl_image *)IxNpeMicrocode_array; + int imgsiz, i, fd, cnt; + const unsigned *arrayptr = IxNpeMicrocode_array; + const char *names[] = { "IXP425", "IXP465", "unknown" }; + int bigendian = 1; + + if (argc > 1) { + if (!strcmp(argv[1], "-le")) + bigendian = 0; + else if (!strcmp(argv[1], "-be")) + bigendian = 1; + else { + printf("Usage: %s <-le|-be>\n", argv[0]); + return EXIT_FAILURE; + } + } + + for (image = (struct dl_image *)arrayptr, cnt=0; + (image->id != 0xfeedf00d) && (image->magic == 0xfeedf00d); + image = (struct dl_image *)(arrayptr), cnt++) + { + unsigned char field[4]; + imgsiz = image->size + 3; + *(unsigned*)field = to_be32(image->id); + char filename[40], slnk[10]; + + sprintf(filename, "NPE-%c.%08x", (field[0] & 0xf) + 'A', + image->id); + if (image->id == 0x00090000) + sprintf(slnk, "NPE-%c-HSS", (field[0] & 0xf) + 'A'); + else + sprintf(slnk, "NPE-%c", (field[0] & 0xf) + 'A'); + + printf("Writing image: %s.NPE_%c Func: %2x Rev: %02x.%02x " + "Size: %5d to: '%s'\n", + names[field[0] >> 4], (field[0] & 0xf) + 'A', + field[1], field[2], field[3], imgsiz*4, filename); + fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0644); + if (fd >= 0) { + for (i=0; i<imgsiz; i++) { + *(unsigned*)field = bigendian ? + to_be32(arrayptr[i]) : + to_le32(arrayptr[i]); + write(fd, field, sizeof(field)); + } + close(fd); + unlink(slnk); + symlink(filename, slnk); + } else { + perror(filename); + } + arrayptr += imgsiz; + } + close(fd); + return 0; +} diff --git a/package/system/ixp4xx-microcode/src/LICENSE.IPL b/package/system/ixp4xx-microcode/src/LICENSE.IPL new file mode 100644 index 0000000000..dad2566cfc --- /dev/null +++ b/package/system/ixp4xx-microcode/src/LICENSE.IPL @@ -0,0 +1,27 @@ +INTEL(R) SOFTWARE LICENSE AGREEMENT + +Copyright (c) 2007, Intel Corporation. +All rights reserved. + +Redistribution. Redistribution and use in binary form, without modification, are permitted +provided that the following conditions are met: +o Redistributions must reproduce the above copyright notice and the following disclaimer in the +documentation and/or other materials provided with the distribution. +o Neither the name of Intel Corporation nor the names of its suppliers may be used to endorse +or promote products derived from this software without specific prior written permission. +o No reverse engineering, decompilation, or disassembly of this software is permitted. + +Limited patent license. Intel Corporation grants a world-wide, royalty-free, non-exclusive +license under patents it now or hereafter owns or controls to make, have made, use, import, +offer to sell and sell (.Utilize.) this software, but solely to the extent that any such patent is +necessary to Utilize the software alone. The patent license shall not apply to any combinations +which include this software. No hardware per se is licensed hereunder. +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. diff --git a/package/system/ltq-dsl/Config.in b/package/system/ltq-dsl/Config.in new file mode 100644 index 0000000000..6d9caf4419 --- /dev/null +++ b/package/system/ltq-dsl/Config.in @@ -0,0 +1,5 @@ +config LANTIQ_DSL_DEBUG + bool "verbose debugging" + depends on PACKAGE_kmod-ltq-dsl + help + Say Y, if you need ltq-dsl to display debug messages. diff --git a/package/system/ltq-dsl/Makefile b/package/system/ltq-dsl/Makefile new file mode 100644 index 0000000000..1fb003a908 --- /dev/null +++ b/package/system/ltq-dsl/Makefile @@ -0,0 +1,177 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ltq-dsl +PKG_BASE_NAME:=drv_dsl_cpe_api_danube +PKG_VERSION:=3.24.4.4 +PKG_RELEASE:=3 +PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/drv_dsl_cpe_api-$(PKG_VERSION) +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ +PKG_MD5SUM:=c45bc531c1ed2ac80f68fb986b63bb87 +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +FW_NAME:=ltq-dsl-fw-0.1 +FW_MD5:=4700a36b66b955b4c5544227267356f4 + +include $(INCLUDE_DIR)/package.mk + +define Download/ltq-dsl-fw + FILE:=$(FW_NAME).tar.bz2 + MD5SUM:=$(FW_MD5) + URL:=http://mirror2.openwrt.org/sources/ +endef +$(eval $(call Download,ltq-dsl-fw)) + +define KernelPackage/ltq-dsl-template + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Lantiq dsl driver for $(1) + URL:=http://www.lantiq.com/ + VARIANT:=$(1) + DEPENDS:=@TARGET_lantiq_$(1) +kmod-atm + FILES:=$(PKG_BUILD_DIR)/src/mei/lantiq_mei.ko \ + $(PKG_BUILD_DIR)/src/drv_dsl_cpe_api.ko \ + $(PKG_BUILD_DIR)/src/mei/lantiq_atm.ko + AUTOLOAD:=$(call AutoLoad,50,lantiq_mei drv_dsl_cpe_api lantiq_atm) +endef + +KernelPackage/ltq-dsl-danube=$(call KernelPackage/ltq-dsl-template,danube) +KernelPackage/ltq-dsl-ase=$(call KernelPackage/ltq-dsl-template,ase) +KernelPackage/ltq-dsl-ar9=$(call KernelPackage/ltq-dsl-template,ar9) +KernelPackage/ltq-dsl-vr9=$(call KernelPackage/ltq-dsl-template,vr9) + +define Package/kmod-ltq-dsl-firmware-template + TITLE+=Firmware Annex-$(1) $(2) + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + VARIANT:= $(1)-$(2) + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_lantiq_$(2) kmod-ltq-dsl-$(2) +endef + +Package/kmod-ltq-dsl-firmware-a-danube=$(call Package/kmod-ltq-dsl-firmware-template,a,danube) +Package/kmod-ltq-dsl-firmware-b-danube=$(call Package/kmod-ltq-dsl-firmware-template,b,danube) +Package/kmod-ltq-dsl-firmware-a-ase=$(call Package/kmod-ltq-dsl-firmware-template,a,ase) +Package/kmod-ltq-dsl-firmware-b-ase=$(call Package/kmod-ltq-dsl-firmware-template,b,ase) +Package/kmod-ltq-dsl-firmware-a-ar9=$(call Package/kmod-ltq-dsl-firmware-template,a,ar9) +Package/kmod-ltq-dsl-firmware-b-ar9=$(call Package/kmod-ltq-dsl-firmware-template,b,ar9) +Package/kmod-ltq-dsl-firmware-a-vr9=$(call Package/kmod-ltq-dsl-firmware-template,a,vr9) +Package/kmod-ltq-dsl-firmware-b-vr9=$(call Package/kmod-ltq-dsl-firmware-template,b,vr9) + +define KernelPackage/ltq-dsl/description + Lantiq DSL driver for AR9, Amazon SE, Danube and VR9 +endef + +define KernelPackage/ltq-dsl/config + source "$(SOURCE)/Config.in" +endef + +IFX_DSL_MAX_DEVICE=1 +IFX_DSL_LINES_PER_DEVICE=1 +IFX_DSL_CHANNELS_PER_LINE=1 + +CONFIGURE_ARGS += --enable-kernel-include="$(LINUX_DIR)/include" \ + --with-max-device="$(IFX_DSL_MAX_DEVICE)" \ + --with-lines-per-device="$(IFX_DSL_LINES_PER_DEVICE)" \ + --with-channels-per-line="$(IFX_DSL_CHANNELS_PER_LINE)" \ + --disable-dsl-delt-static \ + --disable-adsl-led \ + --enable-dsl-ceoc \ + --enable-dsl-pm \ + --enable-dsl-pm-total \ + --enable-dsl-pm-history \ + --enable-dsl-pm-showtime \ + --enable-dsl-pm-channel-counters \ + --enable-dsl-pm-datapath-counters \ + --enable-dsl-pm-line-counters \ + --enable-dsl-pm-channel-thresholds \ + --enable-dsl-pm-datapath-thresholds \ + --enable-dsl-pm-line-thresholds \ + --enable-dsl-pm-optional-parameters \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + ARCH=$(LINUX_KARCH) + +CONFIG_TAG_danube:=DANUBE +CONFIG_TAG_ase:=AMAZON_SE +CONFIG_TAG_ar9:=AR9 +CONFIG_TAG_vr9:=VR9 +CONFIGURE_ARGS += --enable-add-drv-cflags="-DMODULE -DCONFIG_$(CONFIG_TAG_$(BUILD_VARIANT))" + +ifeq ($(BUILD_VARIANT),vr9) +CONFIGURE_ARGS += --enable-vinax +else +CONFIGURE_ARGS += --enable-danube +endif + +ifeq ($(CONFIG_LANTIQ_DSL_DEBUG),y) +CONFIGURE_ARGS += \ + --enable-debug=yes \ + --enable-debug-prints=yes +EXTRA_CFLAGS += -DDEBUG +endif + +EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0 + +define Build/Prepare + $(PKG_UNPACK) + $(INSTALL_DIR) $(PKG_BUILD_DIR)/src/mei/ + $(CP) ./src/* $(PKG_BUILD_DIR)/src/mei/ + $(Build/Patch) + $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(FW_NAME).tar.bz2 +endef + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/Compile + cd $(LINUX_DIR); \ + ARCH=mips CROSS_COMPILE="$(KERNEL_CROSS)" \ + $(MAKE) BUILD_VARIANT=$(BUILD_VARIANT) M=$(PKG_BUILD_DIR)/src/mei/ V=1 modules + $(call Build/Compile/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_ioctl.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_adslmib_ioctl.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_g997.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_types.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_pm.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_api_error.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_danube_ctx.h $(1)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_cmv_danube.h $(1)/usr/include +endef + +define Package/kmod-ltq-dsl-firmware-$(BUILD_VARIANT)/install + $(INSTALL_DIR) $(1)/lib/firmware/ + $(CP) $(PKG_BUILD_DIR)/$(FW_NAME)/ltq-dsl-fw-$(BUILD_VARIANT).bin $(1)/lib/firmware/dsl-fw-$(word 1, $(subst -, ,$(BUILD_VARIANT))).bin + ln -s /lib/firmware/dsl-fw-$(word 1, $(subst -, ,$(BUILD_VARIANT))).bin $(1)/lib/firmware/ModemHWE.bin +endef + +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-danube)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-danube)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-ase)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-ase)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-ar9)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-ar9)) +#$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a-vr9)) +#$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b-vr9)) +$(eval $(call KernelPackage,ltq-dsl-danube)) +$(eval $(call KernelPackage,ltq-dsl-ase)) +$(eval $(call KernelPackage,ltq-dsl-ar9)) +#$(eval $(call KernelPackage,ltq-dsl-vr9)) diff --git a/package/system/ltq-dsl/patches/100-dsl_compat.patch b/package/system/ltq-dsl/patches/100-dsl_compat.patch new file mode 100644 index 0000000000..f892351a65 --- /dev/null +++ b/package/system/ltq-dsl/patches/100-dsl_compat.patch @@ -0,0 +1,125 @@ +--- a/src/include/drv_dsl_cpe_device_danube.h ++++ b/src/include/drv_dsl_cpe_device_danube.h +@@ -24,7 +24,7 @@ + #include "drv_dsl_cpe_simulator_danube.h" + #else + /* Include for the low level driver interface header file */ +-#include "asm/ifx/ifx_mei_bsp.h" ++#include "mei/ifxmips_mei_interface.h" + #endif /* defined(DSL_CPE_SIMULATOR_DRIVER) && defined(WIN32)*/ + + #define DSL_MAX_LINE_NUMBER 1 +--- a/src/common/drv_dsl_cpe_os_linux.c ++++ b/src/common/drv_dsl_cpe_os_linux.c +@@ -11,6 +11,7 @@ + #ifdef __LINUX__ + + #define DSL_INTERN ++#include <linux/device.h> + + #include "drv_dsl_cpe_api.h" + #include "drv_dsl_cpe_api_ioctl.h" +@@ -34,9 +35,13 @@ + static DSL_ssize_t DSL_DRV_Write(DSL_DRV_file_t *pFile, const DSL_char_t * pBuf, + DSL_DRV_size_t nSize, DSL_DRV_offset_t * pLoff); + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_inode_t * pINode, DSL_DRV_file_t * pFile, + DSL_uint_t nCommand, unsigned long nArg); +- ++#else ++static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_file_t * pFile, ++ DSL_uint_t nCommand, unsigned long nArg); ++#endif + static int DSL_DRV_Open(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil); + + static int DSL_DRV_Release(DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil); +@@ -72,7 +77,11 @@ + open: DSL_DRV_Open, + release: DSL_DRV_Release, + write: DSL_DRV_Write, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + ioctl: DSL_DRV_Ioctls, ++#else ++ unlocked_ioctl: DSL_DRV_Ioctls, ++#endif + poll: DSL_DRV_Poll + }; + #else +@@ -168,10 +177,17 @@ + \return Success or failure. + \ingroup Internal + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + static DSL_int_t DSL_DRV_Ioctls(DSL_DRV_inode_t * pINode, + DSL_DRV_file_t * pFile, + DSL_uint_t nCommand, + unsigned long nArg) ++#else ++static DSL_int_t DSL_DRV_Ioctls( ++ DSL_DRV_file_t * pFile, ++ DSL_uint_t nCommand, ++ unsigned long nArg) ++#endif + { + DSL_int_t nErr=0; + DSL_boolean_t bIsInKernel; +@@ -216,16 +232,7 @@ + } + } + } +- +- if (pINode == DSL_NULL) +- { +- bIsInKernel = DSL_TRUE; +- } +- else +- { +- bIsInKernel = DSL_FALSE; +- } +- ++ bIsInKernel = DSL_FALSE; + if ( (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API) || + (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_G997) || + (_IOC_TYPE(nCommand) == DSL_IOC_MAGIC_CPE_API_PM) || +@@ -1058,6 +1065,7 @@ + /* Entry point of driver */ + int __init DSL_ModuleInit(void) + { ++ struct class *dsl_class; + DSL_int_t i; + + printk(DSL_DRV_CRLF DSL_DRV_CRLF "Infineon CPE API Driver version: %s" DSL_DRV_CRLF, +@@ -1104,7 +1112,8 @@ + } + + DSL_DRV_DevNodeInit(); +- ++ dsl_class = class_create(THIS_MODULE, "dsl_cpe_api"); ++ device_create(dsl_class, NULL, MKDEV(DRV_DSL_CPE_API_DEV_MAJOR, 0), NULL, "dsl_cpe_api"); + return 0; + } + +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -17,17 +17,17 @@ + #endif + + #include <asm/ioctl.h> +-#include <linux/autoconf.h> ++#include <generated/autoconf.h> + #include <linux/module.h> + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/ctype.h> + #include <linux/version.h> + #include <linux/spinlock.h> +- ++#include <linux/sched.h> + + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +- #include <linux/utsrelease.h> ++ #include <generated/utsrelease.h> + #endif + + #include <linux/types.h> diff --git a/package/system/ltq-dsl/patches/110-fix_status_polling_loop.patch b/package/system/ltq-dsl/patches/110-fix_status_polling_loop.patch new file mode 100644 index 0000000000..870943d950 --- /dev/null +++ b/package/system/ltq-dsl/patches/110-fix_status_polling_loop.patch @@ -0,0 +1,11 @@ +--- a/src/device/drv_dsl_cpe_device_danube.c ++++ b/src/device/drv_dsl_cpe_device_danube.c +@@ -4069,7 +4069,7 @@ static DSL_Error_t DSL_DRV_DANUBE_XTUSys + + DSL_CTX_WRITE(pContext, nErrCode, xtseCurr, xtseCurr); + +- for (nRetry = 0; nRetry < 20; nRetry++) ++ for (nRetry = 0; nRetry < 20 && bStatusUpdated == DSL_FALSE; nRetry++) + { + /* Get STAT1 info*/ + nErrCode = DSL_DRV_DANUBE_CmvRead(pContext, DSL_CMV_GROUP_STAT, diff --git a/package/system/ltq-dsl/patches/500-portability.patch b/package/system/ltq-dsl/patches/500-portability.patch new file mode 100644 index 0000000000..d74314c77d --- /dev/null +++ b/package/system/ltq-dsl/patches/500-portability.patch @@ -0,0 +1,227 @@ +--- a/configure.in ++++ b/configure.in +@@ -310,7 +310,7 @@ + AC_ARG_ENABLE(kernelbuild, + AC_HELP_STRING(--enable-kernel-build=x,Set the target kernel build path), + [ +- if test -e $enableval/include/linux/autoconf.h; then ++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then + AC_SUBST([KERNEL_BUILD_PATH],[$enableval]) + else + AC_MSG_ERROR([The kernel build directory is not valid or not configured!]) +@@ -333,12 +333,12 @@ + echo Set the lib_ifxos include path $enableval + AC_SUBST([IFXOS_INCLUDE_PATH],[$enableval]) + else +- echo -e Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH ++ echo Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH + AC_SUBST([IFXOS_INCLUDE_PATH],[$DEFAULT_IFXOS_INCLUDE_PATH]) + fi + ], + [ +- echo -e Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH ++ echo Set the default lib_ifxos include path $DEFAULT_IFXOS_INCLUDE_PATH + AC_SUBST([IFXOS_INCLUDE_PATH],[$DEFAULT_IFXOS_INCLUDE_PATH]) + ] + ) +@@ -1702,73 +1702,73 @@ + AC_SUBST([DISTCHECK_CONFIGURE_PARAMS],[$CONFIGURE_OPTIONS]) + + AC_CONFIG_COMMANDS_PRE([ +-echo -e "------------------------------------------------------------------------" +-echo -e " Configuration for drv_dsl_cpe_api:" +-echo -e " Configure model type: $DSL_CONFIG_MODEL_TYPE" +-echo -e " Source code location: $srcdir" +-echo -e " Compiler: $CC" +-echo -e " Compiler c-flags: $CFLAGS" +-echo -e " Extra compiler c-flags: $EXTRA_DRV_CFLAGS" +-echo -e " Host System Type: $host" +-echo -e " Install path: $prefix" +-echo -e " Linux kernel include path: $KERNEL_INCL_PATH" +-echo -e " Linux kernel build path: $KERNEL_BUILD_PATH" +-echo -e " Linux kernel architecture: $KERNEL_ARCH" +-echo -e " Include IFXOS: $INCLUDE_DSL_CPE_API_IFXOS_SUPPORT" +-echo -e " IFXOS include path: $IFXOS_INCLUDE_PATH" +-echo -e " Driver Include Path $DSL_DRIVER_INCL_PATH" +-echo -e " DSL device: $DSL_DEVICE_NAME" +-echo -e " Max device number: $DSL_DRV_MAX_DEVICE_NUMBER" +-echo -e " Channels per line: $DSL_CHANNELS_PER_LINE" +-echo -e " Build lib (only for kernel 2.6) $DSL_CPE_API_LIBRARY_BUILD_2_6" +-echo -e " DSL data led flash frequency: $DSL_DATA_LED_FLASH_FREQUENCY Hz" +-echo -e " Disable debug prints: $DSL_DEBUG_DISABLE" +-echo -e " Preselection of max. debug level: $DSL_DBG_MAX_LEVEL_SET" +-echo -e " Preselected max. debug level: $DSL_DBG_MAX_LEVEL_PRE" +-echo -e " Include deprecated functions: $INCLUDE_DEPRECATED" +-echo -e " Include Device Exception Codes: $INCLUDE_DEVICE_EXCEPTION_CODES" +-echo -e " Include FW request support: $INCLUDE_FW_REQUEST_SUPPORT" +-echo -e " Include ADSL trace buffer: $INCLUDE_DSL_CPE_TRACE_BUFFER" +-echo -e " Include ADSL MIB: $INCLUDE_DSL_ADSL_MIB" +-echo -e " Include ADSL LED: $INCLUDE_ADSL_LED" +-echo -e " Include CEOC: $INCLUDE_DSL_CEOC" +-echo -e " Include config get support: $INCLUDE_DSL_CONFIG_GET" +-echo -e " Include System i/f configuration: $INCLUDE_DSL_SYSTEM_INTERFACE" +-echo -e " Include Resource Statistics: $INCLUDE_DSL_RESOURCE_STATISTICS" +-echo -e " Include Framing Parameters: $INCLUDE_DSL_FRAMING_PARAMETERS" +-echo -e " Include G997 Line Inventory: $INCLUDE_DSL_G997_LINE_INVENTORY" +-echo -e " Include G997 Framing Parameters: $INCLUDE_DSL_G997_FRAMING_PARAMETERS" +-echo -e " Include G997 per tone data: $INCLUDE_DSL_G997_PER_TONE" +-echo -e " Include G997 status: $INCLUDE_DSL_G997_STATUS" +-echo -e " Include G997 alarm: $INCLUDE_DSL_G997_ALARM" +-echo -e " Include DSL Bonding: $INCLUDE_DSL_BONDING" +-echo -e " Include Misc Line Status $INCLUDE_DSL_CPE_MISC_LINE_STATUS" +-echo -e " Include DELT: $INCLUDE_DSL_DELT" +-echo -e " Include DELT data static storage: $DSL_CPE_STATIC_DELT_DATA" +-echo -e " Include PM: $INCLUDE_DSL_PM" +-echo -e " Include PM config: $INCLUDE_DSL_CPE_PM_CONFIG" +-echo -e " Include PM total: $INCLUDE_DSL_CPE_PM_TOTAL_COUNTERS" +-echo -e " Include PM history: $INCLUDE_DSL_CPE_PM_HISTORY" +-echo -e " Include PM showtime: $INCLUDE_DSL_CPE_PM_SHOWTIME_COUNTERS" +-echo -e " Include PM optional: $INCLUDE_DSL_CPE_PM_OPTIONAL_PARAMETERS" +-echo -e " Include PM line: $INCLUDE_DSL_CPE_PM_LINE_COUNTERS" +-echo -e " Include PM line event showtime: $INCLUDE_DSL_CPE_PM_LINE_EVENT_SHOWTIME_COUNTERS" +-echo -e " Include PM channel: $INCLUDE_DSL_CPE_PM_CHANNEL_COUNTERS" +-echo -e " Include PM channel extended: $INCLUDE_DSL_CPE_PM_CHANNEL_EXT_COUNTERS" +-echo -e " Include PM data path: $INCLUDE_DSL_CPE_PM_DATA_PATH_COUNTERS" +-echo -e " Include PM data path failure: $INCLUDE_DSL_CPE_PM_DATA_PATH_FAILURE_COUNTERS" +-echo -e " Include PM ReTx: $INCLUDE_DSL_CPE_PM_RETX_COUNTERS" +-echo -e " Include PM line threshold: $INCLUDE_DSL_CPE_PM_LINE_THRESHOLDS" +-echo -e " Include PM channel threshold: $INCLUDE_DSL_CPE_PM_CHANNEL_THRESHOLDS" +-echo -e " Include PM data path threshold: $INCLUDE_DSL_CPE_PM_DATA_PATH_THRESHOLDS" +-echo -e " Include PM ReTx threshold: $INCLUDE_DSL_CPE_PM_RETX_THRESHOLDS" +-echo -e " Include FW memory free support: $INCLUDE_DSL_FIRMWARE_MEMORY_FREE" +-echo -e "----------------------- deprectated ! ----------------------------------" +-echo -e " Include PM line failure: $INCLUDE_DSL_CPE_PM_LINE_FAILURE_COUNTERS" +-echo -e "" +-echo -e " Settings:" +-echo -e " Configure options: $CONFIGURE_OPTIONS" +-echo -e "------------------------------------------------------------------------" ++echo "------------------------------------------------------------------------" ++echo " Configuration for drv_dsl_cpe_api:" ++echo " Configure model type: $DSL_CONFIG_MODEL_TYPE" ++echo " Source code location: $srcdir" ++echo " Compiler: $CC" ++echo " Compiler c-flags: $CFLAGS" ++echo " Extra compiler c-flags: $EXTRA_DRV_CFLAGS" ++echo " Host System Type: $host" ++echo " Install path: $prefix" ++echo " Linux kernel include path: $KERNEL_INCL_PATH" ++echo " Linux kernel build path: $KERNEL_BUILD_PATH" ++echo " Linux kernel architecture: $KERNEL_ARCH" ++echo " Include IFXOS: $INCLUDE_DSL_CPE_API_IFXOS_SUPPORT" ++echo " IFXOS include path: $IFXOS_INCLUDE_PATH" ++echo " Driver Include Path $DSL_DRIVER_INCL_PATH" ++echo " DSL device: $DSL_DEVICE_NAME" ++echo " Max device number: $DSL_DRV_MAX_DEVICE_NUMBER" ++echo " Channels per line: $DSL_CHANNELS_PER_LINE" ++echo " Build lib (only for kernel 2.6) $DSL_CPE_API_LIBRARY_BUILD_2_6" ++echo " DSL data led flash frequency: $DSL_DATA_LED_FLASH_FREQUENCY Hz" ++echo " Disable debug prints: $DSL_DEBUG_DISABLE" ++echo " Preselection of max. debug level: $DSL_DBG_MAX_LEVEL_SET" ++echo " Preselected max. debug level: $DSL_DBG_MAX_LEVEL_PRE" ++echo " Include deprecated functions: $INCLUDE_DEPRECATED" ++echo " Include Device Exception Codes: $INCLUDE_DEVICE_EXCEPTION_CODES" ++echo " Include FW request support: $INCLUDE_FW_REQUEST_SUPPORT" ++echo " Include ADSL trace buffer: $INCLUDE_DSL_CPE_TRACE_BUFFER" ++echo " Include ADSL MIB: $INCLUDE_DSL_ADSL_MIB" ++echo " Include ADSL LED: $INCLUDE_ADSL_LED" ++echo " Include CEOC: $INCLUDE_DSL_CEOC" ++echo " Include config get support: $INCLUDE_DSL_CONFIG_GET" ++echo " Include System i/f configuration: $INCLUDE_DSL_SYSTEM_INTERFACE" ++echo " Include Resource Statistics: $INCLUDE_DSL_RESOURCE_STATISTICS" ++echo " Include Framing Parameters: $INCLUDE_DSL_FRAMING_PARAMETERS" ++echo " Include G997 Line Inventory: $INCLUDE_DSL_G997_LINE_INVENTORY" ++echo " Include G997 Framing Parameters: $INCLUDE_DSL_G997_FRAMING_PARAMETERS" ++echo " Include G997 per tone data: $INCLUDE_DSL_G997_PER_TONE" ++echo " Include G997 status: $INCLUDE_DSL_G997_STATUS" ++echo " Include G997 alarm: $INCLUDE_DSL_G997_ALARM" ++echo " Include DSL Bonding: $INCLUDE_DSL_BONDING" ++echo " Include Misc Line Status $INCLUDE_DSL_CPE_MISC_LINE_STATUS" ++echo " Include DELT: $INCLUDE_DSL_DELT" ++echo " Include DELT data static storage: $DSL_CPE_STATIC_DELT_DATA" ++echo " Include PM: $INCLUDE_DSL_PM" ++echo " Include PM config: $INCLUDE_DSL_CPE_PM_CONFIG" ++echo " Include PM total: $INCLUDE_DSL_CPE_PM_TOTAL_COUNTERS" ++echo " Include PM history: $INCLUDE_DSL_CPE_PM_HISTORY" ++echo " Include PM showtime: $INCLUDE_DSL_CPE_PM_SHOWTIME_COUNTERS" ++echo " Include PM optional: $INCLUDE_DSL_CPE_PM_OPTIONAL_PARAMETERS" ++echo " Include PM line: $INCLUDE_DSL_CPE_PM_LINE_COUNTERS" ++echo " Include PM line event showtime: $INCLUDE_DSL_CPE_PM_LINE_EVENT_SHOWTIME_COUNTERS" ++echo " Include PM channel: $INCLUDE_DSL_CPE_PM_CHANNEL_COUNTERS" ++echo " Include PM channel extended: $INCLUDE_DSL_CPE_PM_CHANNEL_EXT_COUNTERS" ++echo " Include PM data path: $INCLUDE_DSL_CPE_PM_DATA_PATH_COUNTERS" ++echo " Include PM data path failure: $INCLUDE_DSL_CPE_PM_DATA_PATH_FAILURE_COUNTERS" ++echo " Include PM ReTx: $INCLUDE_DSL_CPE_PM_RETX_COUNTERS" ++echo " Include PM line threshold: $INCLUDE_DSL_CPE_PM_LINE_THRESHOLDS" ++echo " Include PM channel threshold: $INCLUDE_DSL_CPE_PM_CHANNEL_THRESHOLDS" ++echo " Include PM data path threshold: $INCLUDE_DSL_CPE_PM_DATA_PATH_THRESHOLDS" ++echo " Include PM ReTx threshold: $INCLUDE_DSL_CPE_PM_RETX_THRESHOLDS" ++echo " Include FW memory free support: $INCLUDE_DSL_FIRMWARE_MEMORY_FREE" ++echo "----------------------- deprectated ! ----------------------------------" ++echo " Include PM line failure: $INCLUDE_DSL_CPE_PM_LINE_FAILURE_COUNTERS" ++echo "" ++echo " Settings:" ++echo " Configure options: $CONFIGURE_OPTIONS" ++echo "------------------------------------------------------------------------" + ]) + + AC_CONFIG_FILES([Makefile src/Makefile]) +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -303,7 +303,7 @@ + drv_dsl_cpe_api_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_dsl_cpe_api_SOURCES)))" + + drv_dsl_cpe_api.ko: $(drv_dsl_cpe_api_SOURCES) +- @echo -e "drv_dsl_cpe_api: Making Linux 2.6.x kernel object" ++ @echo "drv_dsl_cpe_api: Making Linux 2.6.x kernel object" + if test ! -e common/drv_dsl_cpe_api.c ; then \ + echo "copy source files (as links only!)"; \ + for f in $(filter %.c,$(drv_dsl_cpe_api_SOURCES)); do \ +@@ -311,10 +311,10 @@ + cp -s $(addprefix @abs_srcdir@/,$$f) $(PWD)/`dirname $$f`/ ; \ + done \ + fi +- @echo -e "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild ++ @echo "# drv_dsl_cpe_api: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_dsl_cpe_api_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := $(CFLAGS) -DHAVE_CONFIG_H $(drv_dsl_cpe_api_CFLAGS) $(DSL_DRIVER_INCL_PATH) $(IFXOS_INCLUDE_PATH) -I@abs_srcdir@/include -I$(PWD)/include" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: +--- a/src/include/drv_dsl_cpe_os_linux.h ++++ b/src/include/drv_dsl_cpe_os_linux.h +@@ -16,8 +16,6 @@ + extern "C" { + #endif + +-#include <asm/ioctl.h> +-#include <generated/autoconf.h> + #include <linux/module.h> + #include <linux/kernel.h> + #include <linux/init.h> +@@ -26,8 +24,10 @@ + #include <linux/spinlock.h> + #include <linux/sched.h> + +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +- #include <generated/utsrelease.h> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++#include <linux/utsrelease.h> ++#else ++#include <generated/utsrelease.h> + #endif + + #include <linux/types.h> +@@ -39,7 +39,8 @@ + #include <linux/delay.h> + #include <linux/poll.h> + #include <asm/uaccess.h> +-#include <linux/smp_lock.h> ++//#include <linux/smp_lock.h> ++#include <asm/ioctl.h> + + #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT + /** IFXOS includes*/ diff --git a/package/system/ltq-dsl/src/Makefile b/package/system/ltq-dsl/src/Makefile new file mode 100644 index 0000000000..44d2efbc05 --- /dev/null +++ b/package/system/ltq-dsl/src/Makefile @@ -0,0 +1,23 @@ +obj-m = lantiq_mei.o lantiq_atm.o +lantiq_atm-objs := ifxmips_atm_core.o + +ifeq ($(BUILD_VARIANT),danube) + CFLAGS_MODULE+=-DCONFIG_DANUBE + EXTRA_CFLAGS+=-DCONFIG_DANUBE + lantiq_atm-objs += ifxmips_atm_danube.o +endif +ifeq ($(BUILD_VARIANT),ase) + CFLAGS_MODULE+=-DCONFIG_AMAZON_SE + EXTRA_CFLAGS+=-DCONFIG_AMAZON_SE + lantiq_atm-objs += ifxmips_atm_amazon_se.o +endif +ifeq ($(BUILD_VARIANT),ar9) + CFLAGS_MODULE+=-DCONFIG_AR9 + EXTRA_CFLAGS+=-DCONFIG_AR9 + lantiq_atm-objs += ifxmips_atm_ar9.o +endif +ifeq ($(BUILD_VARIANT),vr9) + CFLAGS_MODULE+=-DCONFIG_VR9 + EXTRA_CFLAGS+=-DCONFIG_VR9 + lantiq_atm-objs += ifxmips_atm_vr9.o +endif diff --git a/package/system/ltq-dsl/src/ifx_atm.h b/package/system/ltq-dsl/src/ifx_atm.h new file mode 100644 index 0000000000..bf045a9754 --- /dev/null +++ b/package/system/ltq-dsl/src/ifx_atm.h @@ -0,0 +1,196 @@ +/****************************************************************************** +** +** FILE NAME : ifx_atm.h +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 17 Jun 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : Global ATM driver header file +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + +#ifndef IFX_ATM_H +#define IFX_ATM_H + + + +/*! + \defgroup IFX_ATM UEIP Project - ATM driver module + \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9. + */ + +/*! + \defgroup IFX_ATM_IOCTL IOCTL Commands + \ingroup IFX_ATM + \brief IOCTL Commands used by user application. + */ + +/*! + \defgroup IFX_ATM_STRUCT Structures + \ingroup IFX_ATM + \brief Structures used by user application. + */ + +/*! + \file ifx_atm.h + \ingroup IFX_ATM + \brief ATM driver header file + */ + + + +/* + * #################################### + * Definition + * #################################### + */ + +/*! + \addtogroup IFX_ATM_STRUCT + */ +/*@{*/ + +/* + * ATM MIB + */ + +/*! + \struct atm_cell_ifEntry_t + \brief Structure used for Cell Level MIB Counters. + + User application use this structure to call IOCTL command "PPE_ATM_MIB_CELL". + */ +typedef struct { + __u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */ + __u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */ + __u32 ifInErrors; /*!< counter of error ingress cells */ + __u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */ + __u32 ifOutErrors; /*!< counter of error egress cells */ +} atm_cell_ifEntry_t; + +/*! + \struct atm_aal5_ifEntry_t + \brief Structure used for AAL5 Frame Level MIB Counters. + + User application use this structure to call IOCTL command "PPE_ATM_MIB_AAL5". + */ +typedef struct { + __u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */ + __u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */ + __u32 ifInUcastPkts; /*!< counter of ingress packets */ + __u32 ifOutUcastPkts; /*!< counter of egress packets */ + __u32 ifInErrors; /*!< counter of error ingress packets */ + __u32 ifInDiscards; /*!< counter of dropped ingress packets */ + __u32 ifOutErros; /*!< counter of error egress packets */ + __u32 ifOutDiscards; /*!< counter of dropped egress packets */ +} atm_aal5_ifEntry_t; + +/*! + \struct atm_aal5_vcc_t + \brief Structure used for per PVC AAL5 Frame Level MIB Counters. + + This structure is a part of structure "atm_aal5_vcc_x_t". + */ +typedef struct { + __u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */ + __u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet + __u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */ +} atm_aal5_vcc_t; + +/*! + \struct atm_aal5_vcc_x_t + \brief Structure used for per PVC AAL5 Frame Level MIB Counters. + + User application use this structure to call IOCTL command "PPE_ATM_MIB_VCC". + */ +typedef struct { + int vpi; /*!< VPI of the VCC to get MIB counters */ + int vci; /*!< VCI of the VCC to get MIB counters */ + atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */ +} atm_aal5_vcc_x_t; + +/*@}*/ + + + +/* + * #################################### + * IOCTL + * #################################### + */ + +/*! + \addtogroup IFX_ATM_IOCTL + */ +/*@{*/ + +/* + * ioctl Command + */ +/*! + \brief ATM IOCTL Magic Number + */ +#define PPE_ATM_IOC_MAGIC 'o' +/*! + \brief ATM IOCTL Command - Get Cell Level MIB Counters + + This command is obsolete. User can get cell level MIB from DSL API. + This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters. + */ +#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t) +/*! + \brief ATM IOCTL Command - Get AAL5 Level MIB Counters + + Get AAL5 packet counters. + This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters. + */ +#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t) +/*! + \brief ATM IOCTL Command - Get Per PVC MIB Counters + + Get AAL5 packet counters for each PVC. + This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters. + */ +#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t) +/*! + \brief Total Number of ATM IOCTL Commands + */ +#define PPE_ATM_IOC_MAXNR 3 + +/*@}*/ + + + +/* + * #################################### + * API + * #################################### + */ + +#ifdef __KERNEL__ +struct port_cell_info { + unsigned int port_num; + unsigned int tx_link_rate[2]; +}; +#endif + + + +#endif // IFX_ATM_H + diff --git a/package/system/ltq-dsl/src/ifxmips_atm.h b/package/system/ltq-dsl/src/ifxmips_atm.h new file mode 100644 index 0000000000..ed90b5d4d7 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm.h @@ -0,0 +1,172 @@ +/****************************************************************************** +** +** FILE NAME : ifx_atm.h +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 17 Jun 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : Global ATM driver header file +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + +#ifndef IFX_ATM_H +#define IFX_ATM_H + + + +/*! + \defgroup IFX_ATM UEIP Project - ATM driver module + \brief UEIP Project - ATM driver module, support Danube, Amazon-SE, AR9, VR9. + */ + +/*! + \defgroup IFX_ATM_IOCTL IOCTL Commands + \ingroup IFX_ATM + \brief IOCTL Commands used by user application. + */ + +/*! + \defgroup IFX_ATM_STRUCT Structures + \ingroup IFX_ATM + \brief Structures used by user application. + */ + +/*! + \file ifx_atm.h + \ingroup IFX_ATM + \brief ATM driver header file + */ + + + +/* + * #################################### + * Definition + * #################################### + */ + +/*! + \addtogroup IFX_ATM_STRUCT + */ +/*@{*/ + +/* + * ATM MIB + */ + +typedef struct { + __u32 ifHCInOctets_h; /*!< byte counter of ingress cells (upper 32 bits, total 64 bits) */ + __u32 ifHCInOctets_l; /*!< byte counter of ingress cells (lower 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_h; /*!< byte counter of egress cells (upper 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_l; /*!< byte counter of egress cells (lower 32 bits, total 64 bits) */ + __u32 ifInErrors; /*!< counter of error ingress cells */ + __u32 ifInUnknownProtos; /*!< counter of unknown ingress cells */ + __u32 ifOutErrors; /*!< counter of error egress cells */ +} atm_cell_ifEntry_t; + +typedef struct { + __u32 ifHCInOctets_h; /*!< byte counter of ingress packets (upper 32 bits, total 64 bits) */ + __u32 ifHCInOctets_l; /*!< byte counter of ingress packets (lower 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_h; /*!< byte counter of egress packets (upper 32 bits, total 64 bits) */ + __u32 ifHCOutOctets_l; /*!< byte counter of egress packets (lower 32 bits, total 64 bits) */ + __u32 ifInUcastPkts; /*!< counter of ingress packets */ + __u32 ifOutUcastPkts; /*!< counter of egress packets */ + __u32 ifInErrors; /*!< counter of error ingress packets */ + __u32 ifInDiscards; /*!< counter of dropped ingress packets */ + __u32 ifOutErros; /*!< counter of error egress packets */ + __u32 ifOutDiscards; /*!< counter of dropped egress packets */ +} atm_aal5_ifEntry_t; + +typedef struct { + __u32 aal5VccCrcErrors; /*!< counter of ingress packets with CRC error */ + __u32 aal5VccSarTimeOuts; /*!< counter of ingress packets with Re-assemble timeout */ //no timer support yet + __u32 aal5VccOverSizedSDUs; /*!< counter of oversized ingress packets */ +} atm_aal5_vcc_t; + +typedef struct { + int vpi; /*!< VPI of the VCC to get MIB counters */ + int vci; /*!< VCI of the VCC to get MIB counters */ + atm_aal5_vcc_t mib_vcc; /*!< structure to get MIB counters */ +} atm_aal5_vcc_x_t; + +/*@}*/ + + + +/* + * #################################### + * IOCTL + * #################################### + */ + +/*! + \addtogroup IFX_ATM_IOCTL + */ +/*@{*/ + +/* + * ioctl Command + */ +/*! + \brief ATM IOCTL Magic Number + */ +#define PPE_ATM_IOC_MAGIC 'o' +/*! + \brief ATM IOCTL Command - Get Cell Level MIB Counters + + This command is obsolete. User can get cell level MIB from DSL API. + This command uses structure "atm_cell_ifEntry_t" as parameter for output of MIB counters. + */ +#define PPE_ATM_MIB_CELL _IOW(PPE_ATM_IOC_MAGIC, 0, atm_cell_ifEntry_t) +/*! + \brief ATM IOCTL Command - Get AAL5 Level MIB Counters + + Get AAL5 packet counters. + This command uses structure "atm_aal5_ifEntry_t" as parameter for output of MIB counters. + */ +#define PPE_ATM_MIB_AAL5 _IOW(PPE_ATM_IOC_MAGIC, 1, atm_aal5_ifEntry_t) +/*! + \brief ATM IOCTL Command - Get Per PVC MIB Counters + + Get AAL5 packet counters for each PVC. + This command uses structure "atm_aal5_vcc_x_t" as parameter for input of VPI/VCI information and output of MIB counters. + */ +#define PPE_ATM_MIB_VCC _IOWR(PPE_ATM_IOC_MAGIC, 2, atm_aal5_vcc_x_t) +/*! + \brief Total Number of ATM IOCTL Commands + */ +#define PPE_ATM_IOC_MAXNR 3 + +/*@}*/ + + + +/* + * #################################### + * API + * #################################### + */ + +#ifdef __KERNEL__ +struct port_cell_info { + unsigned int port_num; + unsigned int tx_link_rate[2]; +}; +#endif + + + +#endif // IFX_ATM_H + diff --git a/package/system/ltq-dsl/src/ifxmips_atm_amazon_se.c b/package/system/ltq-dsl/src/ifxmips_atm_amazon_se.c new file mode 100644 index 0000000000..1028815927 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_amazon_se.c @@ -0,0 +1,324 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_amazon_se.c +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver common source file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <linux/clk.h> +#include <asm/delay.h> + +/* + * Chip Specific Head File + */ +#include <lantiq_soc.h> +#include "ifxmips_compat.h" +#include "ifxmips_atm_core.h" +#include "ifxmips_atm_fw_amazon_se.h" + + + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * EMA Settings + */ +#define EMA_CMD_BUF_LEN 0x0040 +#define EMA_CMD_BASE_ADDR (0x00001580 << 2) +#define EMA_DATA_BUF_LEN 0x0100 +#define EMA_DATA_BASE_ADDR (0x00000B00 << 2) +#define EMA_WRITE_BURST 0x2 +#define EMA_READ_BURST 0x2 + + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Hardware Init/Uninit Functions + */ +static inline void init_pmu(void); +static inline void uninit_pmu(void); +static inline void reset_ppe(void); +static inline void init_ema(void); +static inline void init_mailbox(void); +static inline void init_atm_tc(void); +static inline void clear_share_buffer(void); + + + +/* + * #################################### + * Local Variable + * #################################### + */ + + + +/* + * #################################### + * Local Function + * #################################### + */ + +static inline void init_pmu(void) +{ + //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9)); + //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE); +/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TC_PMU_SETUP(IFX_PMU_ENABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE); + //PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/ + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_enable(clk); +} + +static inline void uninit_pmu(void) +{ +/* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TC_PMU_SETUP(IFX_PMU_DISABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE); + //PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE); + //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE);*/ + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_disable(clk); +} + +static inline void reset_ppe(void) +{ +#ifdef MODULE +/* unsigned int etop_cfg; + unsigned int etop_mdio_cfg; + unsigned int etop_ig_plen_ctrl; + unsigned int enet_mac_cfg; + + etop_cfg = *IFX_PP32_ETOP_CFG; + etop_mdio_cfg = *IFX_PP32_ETOP_MDIO_CFG; + etop_ig_plen_ctrl = *IFX_PP32_ETOP_IG_PLEN_CTRL; + enet_mac_cfg = *IFX_PP32_ENET_MAC_CFG; + + *IFX_PP32_ETOP_CFG = (*IFX_PP32_ETOP_CFG & ~0x03C0) | 0x0001; + + // reset PPE + ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM); + + *IFX_PP32_ETOP_MDIO_CFG = etop_mdio_cfg; + *IFX_PP32_ETOP_IG_PLEN_CTRL = etop_ig_plen_ctrl; + *IFX_PP32_ENET_MAC_CFG = enet_mac_cfg; + *IFX_PP32_ETOP_CFG = etop_cfg;*/ +#endif +} + +static inline void init_ema(void) +{ + IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG); + IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG); + IFX_REG_W32(0x000000FF, EMA_IER); + IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG); +} + +static inline void init_mailbox(void) +{ + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU1_IER); + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU3_IER); +} + +static inline void init_atm_tc(void) +{ + IFX_REG_W32(0x0000, DREG_AT_CTRL); + IFX_REG_W32(0x0000, DREG_AR_CTRL); + IFX_REG_W32(0x0, DREG_AT_IDLE0); + IFX_REG_W32(0x0, DREG_AT_IDLE1); + IFX_REG_W32(0x0, DREG_AR_IDLE0); + IFX_REG_W32(0x0, DREG_AR_IDLE1); + IFX_REG_W32(0x40, RFBI_CFG); + IFX_REG_W32(0x0700, SFSM_DBA0); + IFX_REG_W32(0x0818, SFSM_DBA1); + IFX_REG_W32(0x0930, SFSM_CBA0); + IFX_REG_W32(0x0944, SFSM_CBA1); + IFX_REG_W32(0x14014, SFSM_CFG0); + IFX_REG_W32(0x14014, SFSM_CFG1); + IFX_REG_W32(0x0958, FFSM_DBA0); + IFX_REG_W32(0x09AC, FFSM_DBA1); + IFX_REG_W32(0x10006, FFSM_CFG0); + IFX_REG_W32(0x10006, FFSM_CFG1); + IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC0); + IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC1); +} + +static inline void clear_share_buffer(void) +{ + volatile u32 *p = SB_RAM0_ADDR(0); + unsigned int i; + + for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN; i++ ) + IFX_REG_W32(0, p++); +} + +/* + * Description: + * Download PPE firmware binary code. + * Input: + * src --- u32 *, binary code buffer + * dword_len --- unsigned int, binary code length in DWORD (32-bit) + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len) +{ + volatile u32 *dest; + + if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0 + || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 ) + return IFX_ERROR; + + if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) ) + IFX_REG_W32(0x00, CDM_CFG); + else + IFX_REG_W32(0x04, CDM_CFG); + + /* copy code */ + dest = CDM_CODE_MEMORY(0, 0); + while ( code_dword_len-- > 0 ) + IFX_REG_W32(*code_src++, dest++); + + /* copy data */ + dest = CDM_DATA_MEMORY(0, 0); + while ( data_dword_len-- > 0 ) + IFX_REG_W32(*data_src++, dest++); + + return IFX_SUCCESS; +} + + + +/* + * #################################### + * Global Function + * #################################### + */ + +extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor) +{ + ASSERT(major != NULL, "pointer is NULL"); + ASSERT(minor != NULL, "pointer is NULL"); + +#ifdef VER_IN_FIRMWARE + *major = FW_VER_ID->major; + *minor = FW_VER_ID->minor; +#else + *major = ATM_FW_VER_MAJOR; + *minor = ATM_FW_VER_MINOR; +#endif +} + +void ifx_atm_init_chip(void) +{ + init_pmu(); + + reset_ppe(); + + init_ema(); + + init_mailbox(); + + init_atm_tc(); + + clear_share_buffer(); +} + +void ifx_atm_uninit_chip(void) +{ + uninit_pmu(); +} + +/* + * Description: + * Initialize and start up PP32. + * Input: + * none + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +int ifx_pp32_start(int pp32) +{ + int ret; + + /* download firmware */ + ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data)); + if ( ret != IFX_SUCCESS ) + return ret; + + /* run PP32 */ + IFX_REG_W32(DBG_CTRL_RESTART, PP32_DBG_CTRL); + + /* idle for a while to let PP32 init itself */ + udelay(10); + + return IFX_SUCCESS; +} + +/* + * Description: + * Halt PP32. + * Input: + * none + * Output: + * none + */ +void ifx_pp32_stop(int pp32) +{ + /* halt PP32 */ + IFX_REG_W32(DBG_CTRL_STOP, PP32_DBG_CTRL); +} diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ar9.c b/package/system/ltq-dsl/src/ifxmips_atm_ar9.c new file mode 100644 index 0000000000..31b89f5c84 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ar9.c @@ -0,0 +1,295 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_ar9.c +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver common source file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <linux/clk.h> +#include <asm/delay.h> + +/* + * Chip Specific Head File + */ +#include <lantiq_soc.h> +#include "ifxmips_compat.h" +#define IFX_MEI_BSP 1 +#include "ifxmips_mei_interface.h" +#include "ifxmips_atm_core.h" +#include "ifxmips_atm_ppe_common.h" + #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + #include "ifxmips_atm_fw_ar9_retx.h" +#else + #include "ifxmips_atm_fw_ar9.h" +#endif + + + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * EMA Settings + */ +#define EMA_CMD_BUF_LEN 0x0040 +#define EMA_CMD_BASE_ADDR (0x00003B80 << 2) +#define EMA_DATA_BUF_LEN 0x0100 +#define EMA_DATA_BASE_ADDR (0x00003C00 << 2) +#define EMA_WRITE_BURST 0x2 +#define EMA_READ_BURST 0x2 + + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Hardware Init/Uninit Functions + */ +static inline void init_pmu(void); +static inline void uninit_pmu(void); +static inline void reset_ppe(void); +static inline void init_ema(void); +static inline void init_mailbox(void); +static inline void init_atm_tc(void); +static inline void clear_share_buffer(void); + + + +/* + * #################################### + * Local Variable + * #################################### + */ + + + +/* + * #################################### + * Local Function + * #################################### + */ + +static inline void init_pmu(void) +{ + //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9)); + //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE); +/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TC_PMU_SETUP(IFX_PMU_ENABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/ + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_enable(clk); +} + +static inline void uninit_pmu(void) +{ + /* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TC_PMU_SETUP(IFX_PMU_DISABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);*/ + //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE); + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_disable(clk); +} + +static inline void reset_ppe(void) +{ +#ifdef MODULE + // reset PPE + //ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM); +#endif +} + +static inline void init_ema(void) +{ + IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG); + IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG); + IFX_REG_W32(0x000000FF, EMA_IER); + IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG); +} + +static inline void init_mailbox(void) +{ + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU1_IER); + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU3_IER); +} + +static inline void init_atm_tc(void) +{ +} + +static inline void clear_share_buffer(void) +{ + volatile u32 *p = SB_RAM0_ADDR(0); + unsigned int i; + + for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN + SB_RAM4_DWLEN; i++ ) + IFX_REG_W32(0, p++); +} + +/* + * Description: + * Download PPE firmware binary code. + * Input: + * src --- u32 *, binary code buffer + * dword_len --- unsigned int, binary code length in DWORD (32-bit) + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len) +{ + volatile u32 *dest; + + if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0 + || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 ) + return IFX_ERROR; + + if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) ) + IFX_REG_W32(0x00, CDM_CFG); + else + IFX_REG_W32(0x04, CDM_CFG); + + /* copy code */ + dest = CDM_CODE_MEMORY(0, 0); + while ( code_dword_len-- > 0 ) + IFX_REG_W32(*code_src++, dest++); + + /* copy data */ + dest = CDM_DATA_MEMORY(0, 0); + while ( data_dword_len-- > 0 ) + IFX_REG_W32(*data_src++, dest++); + + return IFX_SUCCESS; +} + + + +/* + * #################################### + * Global Function + * #################################### + */ + +extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor) +{ + ASSERT(major != NULL, "pointer is NULL"); + ASSERT(minor != NULL, "pointer is NULL"); + +#if (defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX) || defined(VER_IN_FIRMWARE) + *major = FW_VER_ID->major; + *minor = FW_VER_ID->minor; +#else + *major = ATM_FW_VER_MAJOR; + *minor = ATM_FW_VER_MINOR; +#endif +} + +void ifx_atm_init_chip(void) +{ + init_pmu(); + + reset_ppe(); + + init_ema(); + + init_mailbox(); + + init_atm_tc(); + + clear_share_buffer(); +} + +void ifx_atm_uninit_chip(void) +{ + uninit_pmu(); +} + +/* + * Description: + * Initialize and start up PP32. + * Input: + * none + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +int ifx_pp32_start(int pp32) +{ + int ret; + + /* download firmware */ + ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data)); + if ( ret != IFX_SUCCESS ) + return ret; + + /* run PP32 */ + IFX_REG_W32(DBG_CTRL_RESTART, PP32_DBG_CTRL(0)); + + /* idle for a while to let PP32 init itself */ + udelay(10); + + return IFX_SUCCESS; +} + +/* + * Description: + * Halt PP32. + * Input: + * none + * Output: + * none + */ +void ifx_pp32_stop(int pp32) +{ + /* halt PP32 */ + IFX_REG_W32(DBG_CTRL_STOP, PP32_DBG_CTRL(0)); +} diff --git a/package/system/ltq-dsl/src/ifxmips_atm_core.c b/package/system/ltq-dsl/src/ifxmips_atm_core.c new file mode 100644 index 0000000000..92853bb886 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_core.c @@ -0,0 +1,4770 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_core.c +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver common source file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + + + +/* + * #################################### + * Version No. + * #################################### + */ + +#define IFX_ATM_VER_MAJOR 1 +#define IFX_ATM_VER_MID 0 +#define IFX_ATM_VER_MINOR 19 + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include <linux/kernel.h> +#include <linux/vmalloc.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <linux/atmdev.h> +#include <linux/atm.h> +#include <linux/clk.h> +#include <linux/interrupt.h> + +/* + * Chip Specific Head File + */ +#include <lantiq_soc.h> +#include "ifxmips_compat.h" +#define IFX_MEI_BSP 1 +#include "ifxmips_mei_interface.h" +#include "ifxmips_atm_core.h" + + + +/* + * #################################### + * Kernel Version Adaption + * #################################### + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) + #define MODULE_PARM_ARRAY(a, b) module_param_array(a, int, NULL, 0) + #define MODULE_PARM(a, b) module_param(a, int, 0) +#else + #define MODULE_PARM_ARRAY(a, b) MODULE_PARM(a, b) +#endif + + + +/*! + \addtogroup IFXMIPS_ATM_MODULE_PARAMS + */ +/*@{*/ +/* + * #################################### + * Parameters to Configure PPE + * #################################### + */ +/*! + \brief QSB cell delay variation due to concurrency + */ +static int qsb_tau = 1; /* QSB cell delay variation due to concurrency */ +/*! + \brief QSB scheduler burst length + */ +static int qsb_srvm = 0x0F; /* QSB scheduler burst length */ +/*! + \brief QSB time step, all legal values are 1, 2, 4 + */ +static int qsb_tstep = 4 ; /* QSB time step, all legal values are 1, 2, 4 */ + +/*! + \brief Write descriptor delay + */ +static int write_descriptor_delay = 0x20; /* Write descriptor delay */ + +/*! + \brief AAL5 padding byte ('~') + */ +static int aal5_fill_pattern = 0x007E; /* AAL5 padding byte ('~') */ +/*! + \brief Max frame size for RX + */ +static int aal5r_max_packet_size = 0x0700; /* Max frame size for RX */ +/*! + \brief Min frame size for RX + */ +static int aal5r_min_packet_size = 0x0000; /* Min frame size for RX */ +/*! + \brief Max frame size for TX + */ +static int aal5s_max_packet_size = 0x0700; /* Max frame size for TX */ +/*! + \brief Min frame size for TX + */ +static int aal5s_min_packet_size = 0x0000; /* Min frame size for TX */ +/*! + \brief Drop error packet in RX path + */ +static int aal5r_drop_error_packet = 1; /* Drop error packet in RX path */ + +/*! + \brief Number of descriptors per DMA RX channel + */ +static int dma_rx_descriptor_length = 128; /* Number of descriptors per DMA RX channel */ +/*! + \brief Number of descriptors per DMA TX channel + */ +static int dma_tx_descriptor_length = 64; /* Number of descriptors per DMA TX channel */ +/*! + \brief PPE core clock cycles between descriptor write and effectiveness in external RAM + */ +static int dma_rx_clp1_descriptor_threshold = 38; +/*@}*/ + +MODULE_PARM(qsb_tau, "i"); +MODULE_PARM_DESC(qsb_tau, "Cell delay variation. Value must be > 0"); +MODULE_PARM(qsb_srvm, "i"); +MODULE_PARM_DESC(qsb_srvm, "Maximum burst size"); +MODULE_PARM(qsb_tstep, "i"); +MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4"); + +MODULE_PARM(write_descriptor_delay, "i"); +MODULE_PARM_DESC(write_descriptor_delay, "PPE core clock cycles between descriptor write and effectiveness in external RAM"); + +MODULE_PARM(aal5_fill_pattern, "i"); +MODULE_PARM_DESC(aal5_fill_pattern, "Filling pattern (PAD) for AAL5 frames"); +MODULE_PARM(aal5r_max_packet_size, "i"); +MODULE_PARM_DESC(aal5r_max_packet_size, "Max packet size in byte for downstream AAL5 frames"); +MODULE_PARM(aal5r_min_packet_size, "i"); +MODULE_PARM_DESC(aal5r_min_packet_size, "Min packet size in byte for downstream AAL5 frames"); +MODULE_PARM(aal5s_max_packet_size, "i"); +MODULE_PARM_DESC(aal5s_max_packet_size, "Max packet size in byte for upstream AAL5 frames"); +MODULE_PARM(aal5s_min_packet_size, "i"); +MODULE_PARM_DESC(aal5s_min_packet_size, "Min packet size in byte for upstream AAL5 frames"); +MODULE_PARM(aal5r_drop_error_packet, "i"); +MODULE_PARM_DESC(aal5r_drop_error_packet, "Non-zero value to drop error packet for downstream"); + +MODULE_PARM(dma_rx_descriptor_length, "i"); +MODULE_PARM_DESC(dma_rx_descriptor_length, "Number of descriptor assigned to DMA RX channel (>16)"); +MODULE_PARM(dma_tx_descriptor_length, "i"); +MODULE_PARM_DESC(dma_tx_descriptor_length, "Number of descriptor assigned to DMA TX channel (>16)"); +MODULE_PARM(dma_rx_clp1_descriptor_threshold, "i"); +MODULE_PARM_DESC(dma_rx_clp1_descriptor_threshold, "Descriptor threshold for cells with cell loss priority 1"); + + + +/* + * #################################### + * Definition + * #################################### + */ + +#define ENABLE_LED_FRAMEWORK 1 + +#define DUMP_SKB_LEN ~0 + + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Network Operations + */ +static int ppe_ioctl(struct atm_dev *, unsigned int, void *); +static int ppe_open(struct atm_vcc *); +static void ppe_close(struct atm_vcc *); +static int ppe_send(struct atm_vcc *, struct sk_buff *); +static int ppe_send_oam(struct atm_vcc *, void *, int); +static int ppe_change_qos(struct atm_vcc *, struct atm_qos *, int); + +/* + * ADSL LED + */ +static INLINE void adsl_led_flash(void); + +/* + * 64-bit operation used by MIB calculation + */ +static INLINE void u64_add_u32(ppe_u64_t, unsigned int, ppe_u64_t *); + +/* + * buffer manage functions + */ +static INLINE struct sk_buff* alloc_skb_rx(void); +static INLINE struct sk_buff* alloc_skb_tx(unsigned int); +struct sk_buff* atm_alloc_tx(struct atm_vcc *, unsigned int); +static INLINE void atm_free_tx_skb_vcc(struct sk_buff *, struct atm_vcc *); +static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int); +static INLINE int get_tx_desc(unsigned int); + +/* + * mailbox handler and signal function + */ +static INLINE void mailbox_oam_rx_handler(void); +static INLINE void mailbox_aal_rx_handler(void); +#if defined(ENABLE_TASKLET) && ENABLE_TASKLET + static void do_ppe_tasklet(unsigned long); +#endif +static irqreturn_t mailbox_irq_handler(int, void *); +static INLINE void mailbox_signal(unsigned int, int); + +/* + * QSB & HTU setting functions + */ +static void set_qsb(struct atm_vcc *, struct atm_qos *, unsigned int); +static void qsb_global_set(void); +static INLINE void set_htu_entry(unsigned int, unsigned int, unsigned int, int, int); +static INLINE void clear_htu_entry(unsigned int); +static void validate_oam_htu_entry(void); +static void invalidate_oam_htu_entry(void); + +/* + * look up for connection ID + */ +static INLINE int find_vpi(unsigned int); +static INLINE int find_vpivci(unsigned int, unsigned int); +static INLINE int find_vcc(struct atm_vcc *); + +/* + * ReTX functions + */ +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + static void retx_polling_func(unsigned long); + static int init_atm_tc_retrans_param(void); + static void clear_atm_tc_retrans_param(void); +#endif + + +/* + * Debug Functions + */ +#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB + static void dump_skb(struct sk_buff *, unsigned int, char *, int, int, int); +#else + #define dump_skb(skb, len, title, port, ch, is_tx) do {} while (0) +#endif +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + static void skb_swap(struct sk_buff *, unsigned int); +#else + #define skb_swap(skb, byteoff) do {} while (0) +#endif + +/* + * Proc File Functions + */ +static INLINE void proc_file_create(void); +static INLINE void proc_file_delete(void); +static int proc_read_version(char *, char **, off_t, int, int *, void *); +static int proc_read_mib(char *, char **, off_t, int, int *, void *); +static int proc_write_mib(struct file *, const char *, unsigned long, void *); +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + static int proc_read_retx_mib(char *, char **, off_t, int, int *, void *); + static int proc_write_retx_mib(struct file *, const char *, unsigned long, void *); +#endif +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + static int proc_read_dbg(char *, char **, off_t, int, int *, void *); + static int proc_write_dbg(struct file *, const char *, unsigned long, void *); + static int proc_write_mem(struct file *, const char *, unsigned long, void *); + #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE) + static int proc_read_pp32(char *, char **, off_t, int, int *, void *); + static int proc_write_pp32(struct file *, const char *, unsigned long, void *); + #endif +#endif +#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC + static int proc_read_htu(char *, char **, off_t, int, int *, void *); + static int proc_read_txq(char *, char **, off_t, int, int *, void *); + #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + static int proc_read_retx_fw(char *, char **, off_t, int, int *, void *); + static int proc_read_retx_stats(char *, char **, off_t, int, int *, void *); + static int proc_write_retx_stats(struct file *, const char *, unsigned long, void *); + static int proc_read_retx_cfg(char *, char **, off_t, int, int *, void *); + static int proc_write_retx_cfg(struct file *, const char *, unsigned long, void *); + static int proc_read_retx_dsl_param(char *, char **, off_t, int, int *, void *); + #endif +#endif + +/* + * Proc Help Functions + */ +static int stricmp(const char *, const char *); +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + static int strincmp(const char *, const char *, int); + static int get_token(char **, char **, int *, int *); + static unsigned int get_number(char **, int *, int); + static void ignore_space(char **, int *); +#endif +static INLINE int ifx_atm_version(char *); + +/* + * Init & clean-up functions + */ +static INLINE void check_parameters(void); +static INLINE int init_priv_data(void); +static INLINE void clear_priv_data(void); +static INLINE void init_rx_tables(void); +static INLINE void init_tx_tables(void); + +/* + * Exteranl Function + */ +#if defined(CONFIG_IFX_OAM) || defined(CONFIG_IFX_OAM_MODULE) + extern void ifx_push_oam(unsigned char *); +#else + static inline void ifx_push_oam(unsigned char *dummy) {} +#endif +#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE) + #if !defined(ENABLE_LED_FRAMEWORK) || !ENABLE_LED_FRAMEWORK + extern int ifx_mei_atm_led_blink(void) __attribute__ ((weak)); + #endif + extern int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr) __attribute__ ((weak)); +#else + #if !defined(ENABLE_LED_FRAMEWORK) || !ENABLE_LED_FRAMEWORK + static inline int ifx_mei_atm_led_blink(void) { return IFX_SUCCESS; } + #endif + static inline int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr) + { + if ( is_showtime != NULL ) + *is_showtime = 0; + return IFX_SUCCESS; + } +#endif + +/* + * External variable + */ +struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL; + + +//extern struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int); +#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE) + extern int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) __attribute__ ((weak)); + extern int (*ifx_mei_atm_showtime_exit)(void) __attribute__ ((weak)); +#else + int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL; + EXPORT_SYMBOL(ifx_mei_atm_showtime_enter); + int (*ifx_mei_atm_showtime_exit)(void) = NULL; + EXPORT_SYMBOL(ifx_mei_atm_showtime_exit); +#endif + + + +/* + * #################################### + * Local Variable + * #################################### + */ + +static struct atm_priv_data g_atm_priv_data; + +static struct atmdev_ops g_ifx_atm_ops = { + .open = ppe_open, + .close = ppe_close, + .ioctl = ppe_ioctl, + .send = ppe_send, + .send_oam = ppe_send_oam, + .change_qos = ppe_change_qos, + .owner = THIS_MODULE, +}; + +#if defined(ENABLE_TASKLET) && ENABLE_TASKLET + DECLARE_TASKLET(g_dma_tasklet, do_ppe_tasklet, 0); +#endif + +static int g_showtime = 0; +static void *g_xdata_addr = NULL; + +#if 0 /*--- defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK ---*/ + static void *g_data_led_trigger = NULL; +#endif + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + static unsigned long g_retx_playout_buffer = 0; + + static volatile int g_retx_htu = 1; + static struct dsl_param g_dsl_param = {0}; + static int g_retx_polling_cnt = HZ; + static struct timeval g_retx_polling_start = {0}, g_retx_polling_end = {0}; + static struct timer_list g_retx_polling_timer; +#endif + +unsigned int ifx_atm_dbg_enable = 0; + +static struct proc_dir_entry* g_atm_dir = NULL; + + + +/* + * #################################### + * Local Function + * #################################### + */ + +static int ppe_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) +{ + int ret = 0; + atm_cell_ifEntry_t mib_cell; + atm_aal5_ifEntry_t mib_aal5; + atm_aal5_vcc_x_t mib_vcc; + unsigned int value; + int conn; + + if ( _IOC_TYPE(cmd) != PPE_ATM_IOC_MAGIC + || _IOC_NR(cmd) >= PPE_ATM_IOC_MAXNR ) + return -ENOTTY; + + if ( _IOC_DIR(cmd) & _IOC_READ ) + ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd)); + else if ( _IOC_DIR(cmd) & _IOC_WRITE ) + ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd)); + if ( ret ) + return -EFAULT; + + switch ( cmd ) + { + case PPE_ATM_MIB_CELL: /* cell level MIB */ + /* These MIB should be read at ARC side, now put zero only. */ + mib_cell.ifHCInOctets_h = 0; + mib_cell.ifHCInOctets_l = 0; + mib_cell.ifHCOutOctets_h = 0; + mib_cell.ifHCOutOctets_l = 0; + mib_cell.ifInErrors = 0; + mib_cell.ifInUnknownProtos = WAN_MIB_TABLE->wrx_drophtu_cell; + mib_cell.ifOutErrors = 0; + + ret = sizeof(mib_cell) - copy_to_user(arg, &mib_cell, sizeof(mib_cell)); + break; + + case PPE_ATM_MIB_AAL5: /* AAL5 MIB */ + value = WAN_MIB_TABLE->wrx_total_byte; + u64_add_u32(g_atm_priv_data.wrx_total_byte, value - g_atm_priv_data.prev_wrx_total_byte, &g_atm_priv_data.wrx_total_byte); + g_atm_priv_data.prev_wrx_total_byte = value; + mib_aal5.ifHCInOctets_h = g_atm_priv_data.wrx_total_byte.h; + mib_aal5.ifHCInOctets_l = g_atm_priv_data.wrx_total_byte.l; + + value = WAN_MIB_TABLE->wtx_total_byte; + u64_add_u32(g_atm_priv_data.wtx_total_byte, value - g_atm_priv_data.prev_wtx_total_byte, &g_atm_priv_data.wtx_total_byte); + g_atm_priv_data.prev_wtx_total_byte = value; + mib_aal5.ifHCOutOctets_h = g_atm_priv_data.wtx_total_byte.h; + mib_aal5.ifHCOutOctets_l = g_atm_priv_data.wtx_total_byte.l; + + mib_aal5.ifInUcastPkts = g_atm_priv_data.wrx_pdu; + mib_aal5.ifOutUcastPkts = WAN_MIB_TABLE->wtx_total_pdu; + mib_aal5.ifInErrors = WAN_MIB_TABLE->wrx_err_pdu; + mib_aal5.ifInDiscards = WAN_MIB_TABLE->wrx_dropdes_pdu + g_atm_priv_data.wrx_drop_pdu; + mib_aal5.ifOutErros = g_atm_priv_data.wtx_err_pdu; + mib_aal5.ifOutDiscards = g_atm_priv_data.wtx_drop_pdu; + + ret = sizeof(mib_aal5) - copy_to_user(arg, &mib_aal5, sizeof(mib_aal5)); + break; + + case PPE_ATM_MIB_VCC: /* VCC related MIB */ + copy_from_user(&mib_vcc, arg, sizeof(mib_vcc)); + conn = find_vpivci(mib_vcc.vpi, mib_vcc.vci); + if ( conn >= 0 ) + { + mib_vcc.mib_vcc.aal5VccCrcErrors = g_atm_priv_data.conn[conn].aal5_vcc_crc_err; + mib_vcc.mib_vcc.aal5VccOverSizedSDUs = g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu; + mib_vcc.mib_vcc.aal5VccSarTimeOuts = 0; /* no timer support */ + ret = sizeof(mib_vcc) - copy_to_user(arg, &mib_vcc, sizeof(mib_vcc)); + } + else + ret = -EINVAL; + break; + + default: + ret = -ENOIOCTLCMD; + } + + return ret; +} + +static int ppe_open(struct atm_vcc *vcc) +{ + int ret; + short vpi = vcc->vpi; + int vci = vcc->vci; + struct port *port = &g_atm_priv_data.port[(int)vcc->dev->dev_data]; + int conn; + int f_enable_irq = 0; +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + int sys_flag; +#endif + + if ( vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0 ) + return -EPROTONOSUPPORT; + +#if !defined(DISABLE_QOS_WORKAROUND) || !DISABLE_QOS_WORKAROUND + /* check bandwidth */ + + if (vcc->qos.txtp.traffic_class == ATM_CBR && + vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + { + printk("CBR set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + if(vcc->qos.txtp.traffic_class == ATM_VBR_RT && + vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + { + printk("VBR RT set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + + if (vcc->qos.txtp.traffic_class == ATM_VBR_NRT && + vcc->qos.txtp.scr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + { + printk("VBR NRT set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + + if (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS && + vcc->qos.txtp.min_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + { + printk("UBR PLUS set. %s, line %d returns EINVAL\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + +#endif + + /* check existing vpi,vci */ + conn = find_vpivci(vpi, vci); + if ( conn >= 0 ) { + ret = -EADDRINUSE; + goto PPE_OPEN_EXIT; + } + + /* check whether it need to enable irq */ + if ( g_atm_priv_data.conn_table == 0 ) + f_enable_irq = 1; + + /* allocate connection */ + for ( conn = 0; conn < MAX_PVC_NUMBER; conn++ ) { + if ( test_and_set_bit(conn, &g_atm_priv_data.conn_table) == 0 ) { + g_atm_priv_data.conn[conn].vcc = vcc; + break; + } + } + if ( conn == MAX_PVC_NUMBER ) + { + printk("max_pvc_number reached\n"); + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + + /* reserve bandwidth */ + switch ( vcc->qos.txtp.traffic_class ) { + case ATM_CBR: + case ATM_VBR_RT: + port->tx_current_cell_rate += vcc->qos.txtp.max_pcr; + break; + case ATM_VBR_NRT: + port->tx_current_cell_rate += vcc->qos.txtp.scr; + break; + case ATM_UBR_PLUS: + port->tx_current_cell_rate += vcc->qos.txtp.min_pcr; + break; + } + + /* set qsb */ + set_qsb(vcc, &vcc->qos, conn); + + /* update atm_vcc structure */ + vcc->itf = (int)vcc->dev->dev_data; + vcc->vpi = vpi; + vcc->vci = vci; + set_bit(ATM_VF_READY, &vcc->flags); + + /* enable irq */ + if (f_enable_irq ) { + ifx_atm_alloc_tx = atm_alloc_tx; + + *MBOX_IGU1_ISRC = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM); + *MBOX_IGU1_IER = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM); + + enable_irq(PPE_MAILBOX_IGU1_INT); + } + + /* set port */ + WTX_QUEUE_CONFIG(conn + FIRST_QSB_QID)->sbid = (int)vcc->dev->dev_data; + + /* set htu entry */ + set_htu_entry(vpi, vci, conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 0); + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + // ReTX: occupy second QID + local_irq_save(sys_flag); + if ( g_retx_htu && vcc->qos.aal == ATM_AAL5 ) + { + int retx_conn = (conn + 8) % 16; // ReTX queue + + if ( retx_conn < MAX_PVC_NUMBER && test_and_set_bit(retx_conn, &g_atm_priv_data.conn_table) == 0 ) { + g_atm_priv_data.conn[retx_conn].vcc = vcc; + set_htu_entry(vpi, vci, retx_conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 1); + } + } + local_irq_restore(sys_flag); +#endif + + ret = 0; + +PPE_OPEN_EXIT: + return ret; +} + +static void ppe_close(struct atm_vcc *vcc) +{ + int conn; + struct port *port; + struct connection *connection; +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + int sys_flag; +#endif + + if ( vcc == NULL ) + return; + + /* get connection id */ + conn = find_vcc(vcc); + if ( conn < 0 ) { + err("can't find vcc"); + goto PPE_CLOSE_EXIT; + } + connection = &g_atm_priv_data.conn[conn]; + port = &g_atm_priv_data.port[connection->port]; + + /* clear htu */ + clear_htu_entry(conn); + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + // ReTX: release second QID + local_irq_save(sys_flag); + if ( g_retx_htu && vcc->qos.aal == ATM_AAL5 ) + { + int retx_conn = (conn + 8) % 16; // ReTX queue + + if ( retx_conn < MAX_PVC_NUMBER && g_atm_priv_data.conn[retx_conn].vcc == vcc ) { + clear_htu_entry(retx_conn); + g_atm_priv_data.conn[retx_conn].vcc = NULL; + g_atm_priv_data.conn[retx_conn].aal5_vcc_crc_err = 0; + g_atm_priv_data.conn[retx_conn].aal5_vcc_oversize_sdu = 0; + clear_bit(retx_conn, &g_atm_priv_data.conn_table); + } + } + local_irq_restore(sys_flag); +#endif + + /* release connection */ + connection->vcc = NULL; + connection->aal5_vcc_crc_err = 0; + connection->aal5_vcc_oversize_sdu = 0; + clear_bit(conn, &g_atm_priv_data.conn_table); + + /* disable irq */ + if ( g_atm_priv_data.conn_table == 0 ) { + disable_irq(PPE_MAILBOX_IGU1_INT); + ifx_atm_alloc_tx = NULL; + } + + /* release bandwidth */ + switch ( vcc->qos.txtp.traffic_class ) + { + case ATM_CBR: + case ATM_VBR_RT: + port->tx_current_cell_rate -= vcc->qos.txtp.max_pcr; + break; + case ATM_VBR_NRT: + port->tx_current_cell_rate -= vcc->qos.txtp.scr; + break; + case ATM_UBR_PLUS: + port->tx_current_cell_rate -= vcc->qos.txtp.min_pcr; + break; + } + +PPE_CLOSE_EXIT: + return; +} + +static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb) +{ + int ret; + int conn; + int desc_base; + struct tx_descriptor reg_desc = {0}; + + if ( vcc == NULL || skb == NULL ) + return -EINVAL; + + skb_orphan(skb); + skb_get(skb); + atm_free_tx_skb_vcc(skb, vcc); + + conn = find_vcc(vcc); + if ( conn < 0 ) { + ret = -EINVAL; + goto FIND_VCC_FAIL; + } + + if ( !g_showtime ) { + err("not in showtime"); + ret = -EIO; + goto PPE_SEND_FAIL; + } + + if ( vcc->qos.aal == ATM_AAL5 ) { + int byteoff; + int datalen; + struct tx_inband_header *header; + + datalen = skb->len; + byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); + + if ( skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH ) { + struct sk_buff *new_skb; + + new_skb = alloc_skb_tx(datalen); + if ( new_skb == NULL ) { + err("ALLOC_SKB_TX_FAIL"); + ret = -ENOMEM; + goto PPE_SEND_FAIL; + } + skb_put(new_skb, datalen); + memcpy(new_skb->data, skb->data, datalen); + dev_kfree_skb_any(skb); + skb = new_skb; + byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1); + } + + skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH); + + header = (struct tx_inband_header *)skb->data; + + /* setup inband trailer */ + header->uu = 0; + header->cpi = 0; + header->pad = aal5_fill_pattern; + header->res1 = 0; + + /* setup cell header */ + header->clp = (vcc->atm_options & ATM_ATMOPT_CLP) ? 1 : 0; + header->pti = ATM_PTI_US0; + header->vci = vcc->vci; + header->vpi = vcc->vpi; + header->gfc = 0; + + /* setup descriptor */ + reg_desc.dataptr = (unsigned int)skb->data >> 2; + reg_desc.datalen = datalen; + reg_desc.byteoff = byteoff; + reg_desc.iscell = 0; + } + else { + /* if data pointer is not aligned, allocate new sk_buff */ + if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) { + struct sk_buff *new_skb; + + err("skb->data not aligned"); + + new_skb = alloc_skb_tx(skb->len); + if ( new_skb == NULL ) { + err("ALLOC_SKB_TX_FAIL"); + ret = -ENOMEM; + goto PPE_SEND_FAIL; + } + skb_put(new_skb, skb->len); + memcpy(new_skb->data, skb->data, skb->len); + dev_kfree_skb_any(skb); + skb = new_skb; + } + + reg_desc.dataptr = (unsigned int)skb->data >> 2; + reg_desc.datalen = skb->len; + reg_desc.byteoff = 0; + reg_desc.iscell = 1; + } + + reg_desc.own = 1; + reg_desc.c = 1; + reg_desc.sop = reg_desc.eop = 1; + + desc_base = get_tx_desc(conn); + if ( desc_base < 0 ) { + err("ALLOC_TX_CONNECTION_FAIL"); + ret = -EIO; + goto PPE_SEND_FAIL; + } + + if ( vcc->stats ) + atomic_inc(&vcc->stats->tx); + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wtx_pdu++; + + /* update descriptor send pointer */ + if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL ) + dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]); + g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb; + + /* write discriptor to memory and write back cache */ +#ifdef CONFIG_DEBUG_SLAB + /* be sure that "redzone 1" is written back to memory */ + dma_cache_wback((unsigned long)skb->head, 32); +#endif + dma_cache_wback((unsigned long)skb_shinfo(skb), sizeof(struct skb_shared_info)); + dma_cache_wback((unsigned long)skb->data, skb->len); + g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc; + + dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1); + + mailbox_signal(conn, 1); + + adsl_led_flash(); + + return 0; + +FIND_VCC_FAIL: + err("FIND_VCC_FAIL"); + g_atm_priv_data.wtx_err_pdu++; + dev_kfree_skb_any(skb); + return ret; + +PPE_SEND_FAIL: + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wtx_drop_pdu++; + if ( vcc->stats ) + atomic_inc(&vcc->stats->tx_err); + dev_kfree_skb_any(skb); + return ret; +} + +static int ppe_send_oam(struct atm_vcc *vcc, void *cell, int flags) +{ + int conn; + struct uni_cell_header *uni_cell_header = (struct uni_cell_header *)cell; + int desc_base; + struct sk_buff *skb; + struct tx_descriptor reg_desc = {0}; + + if ( ((uni_cell_header->pti == ATM_PTI_SEGF5 || uni_cell_header->pti == ATM_PTI_E2EF5) + && find_vpivci(uni_cell_header->vpi, uni_cell_header->vci) < 0) + || ((uni_cell_header->vci == 0x03 || uni_cell_header->vci == 0x04) + && find_vpi(uni_cell_header->vpi) < 0) ) + return -EINVAL; + + if ( !g_showtime ) { + err("not in showtime"); + return -EIO; + } + + conn = find_vcc(vcc); + if ( conn < 0 ) { + err("FIND_VCC_FAIL"); + return -EINVAL; + } + + skb = alloc_skb_tx(CELL_SIZE); + if ( skb == NULL ) { + err("ALLOC_SKB_TX_FAIL"); + return -ENOMEM; + } + memcpy(skb->data, cell, CELL_SIZE); + + reg_desc.dataptr = (unsigned int)skb->data >> 2; + reg_desc.datalen = CELL_SIZE; + reg_desc.byteoff = 0; + reg_desc.iscell = 1; + + reg_desc.own = 1; + reg_desc.c = 1; + reg_desc.sop = reg_desc.eop = 1; + + desc_base = get_tx_desc(conn); + if ( desc_base < 0 ) { + dev_kfree_skb_any(skb); + err("ALLOC_TX_CONNECTION_FAIL"); + return -EIO; + } + + if ( vcc->stats ) + atomic_inc(&vcc->stats->tx); + + /* update descriptor send pointer */ + if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL ) + dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]); + g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb; + + /* write discriptor to memory and write back cache */ + g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc; + dma_cache_wback((unsigned long)skb->data, CELL_SIZE); + + dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1); + + if ( vcc->qos.aal == ATM_AAL5 && (ifx_atm_dbg_enable & DBG_ENABLE_MASK_MAC_SWAP) ) { + skb_swap(skb, reg_desc.byteoff); + } + + mailbox_signal(conn, 1); + + adsl_led_flash(); + + return 0; +} + +static int ppe_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags) +{ + int conn; + + if ( vcc == NULL || qos == NULL ) + return -EINVAL; + + conn = find_vcc(vcc); + if ( conn < 0 ) + return -EINVAL; + + set_qsb(vcc, qos, conn); + + return 0; +} + +static INLINE void adsl_led_flash(void) +{ +#if 0 +#if defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK + if ( g_data_led_trigger != NULL ) + ifx_led_trigger_activate(g_data_led_trigger); +#else + if (!IS_ERR(&ifx_mei_atm_led_blink) && &ifx_mei_atm_led_blink ) + ifx_mei_atm_led_blink(); +#endif +#endif +} + +/* + * Description: + * Add a 32-bit value to 64-bit value, and put result in a 64-bit variable. + * Input: + * opt1 --- ppe_u64_t, first operand, a 64-bit unsigned integer value + * opt2 --- unsigned int, second operand, a 32-bit unsigned integer value + * ret --- ppe_u64_t, pointer to a variable to hold result + * Output: + * none + */ +static INLINE void u64_add_u32(ppe_u64_t opt1, unsigned int opt2, ppe_u64_t *ret) +{ + ret->l = opt1.l + opt2; + if ( ret->l < opt1.l || ret->l < opt2 ) + ret->h++; +} + +static INLINE struct sk_buff* alloc_skb_rx(void) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb(RX_DMA_CH_AAL_BUF_SIZE + DATA_BUFFER_ALIGNMENT); + if ( skb != NULL ) { + /* must be burst length alignment */ + if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) + skb_reserve(skb, ~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)); + /* pub skb in reserved area "skb->data - 4" */ + *((struct sk_buff **)skb->data - 1) = skb; + /* write back and invalidate cache */ + dma_cache_wback_inv((unsigned long)skb->data - sizeof(skb), sizeof(skb)); + /* invalidate cache */ + dma_cache_inv((unsigned long)skb->data, (unsigned int)skb->end - (unsigned int)skb->data); + } + + return skb; +} + +static INLINE struct sk_buff* alloc_skb_tx(unsigned int size) +{ + struct sk_buff *skb; + + /* allocate memory including header and padding */ + size += TX_INBAND_HEADER_LENGTH + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES; + size &= ~(DATA_BUFFER_ALIGNMENT - 1); + skb = dev_alloc_skb(size + DATA_BUFFER_ALIGNMENT); + /* must be burst length alignment */ + if ( skb != NULL ) + skb_reserve(skb, (~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)) + TX_INBAND_HEADER_LENGTH); + return skb; +} + +struct sk_buff* atm_alloc_tx(struct atm_vcc *vcc, unsigned int size) +{ + int conn; + struct sk_buff *skb; + + /* oversize packet */ + if ( size > aal5s_max_packet_size ) { + err("atm_alloc_tx: oversize packet"); + return NULL; + } + /* send buffer overflow */ + if ( atomic_read(&sk_atm(vcc)->sk_wmem_alloc) && !atm_may_send(vcc, size) ) { + err("atm_alloc_tx: send buffer overflow"); + return NULL; + } + conn = find_vcc(vcc); + if ( conn < 0 ) { + err("atm_alloc_tx: unknown VCC"); + return NULL; + } + + skb = dev_alloc_skb(size); + if ( skb == NULL ) { + err("atm_alloc_tx: sk buffer is used up"); + return NULL; + } + + atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); + + return skb; +} + +static INLINE void atm_free_tx_skb_vcc(struct sk_buff *skb, struct atm_vcc *vcc) +{ + if ( vcc->pop != NULL ) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); +} + +static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int dataptr) +{ + unsigned int skb_dataptr; + struct sk_buff *skb; + + skb_dataptr = ((dataptr - 1) << 2) | KSEG1; + skb = *(struct sk_buff **)skb_dataptr; + + ASSERT((unsigned int)skb >= KSEG0, "invalid skb - skb = %#08x, dataptr = %#08x", (unsigned int)skb, dataptr); + ASSERT(((unsigned int)skb->data | KSEG1) == ((dataptr << 2) | KSEG1), "invalid skb - skb = %#08x, skb->data = %#08x, dataptr = %#08x", (unsigned int)skb, (unsigned int)skb->data, dataptr); + + return skb; +} + +static INLINE int get_tx_desc(unsigned int conn) +{ + int desc_base = -1; + struct connection *p_conn = &g_atm_priv_data.conn[conn]; + + if ( p_conn->tx_desc[p_conn->tx_desc_pos].own == 0 ) { + desc_base = p_conn->tx_desc_pos; + if ( ++(p_conn->tx_desc_pos) == dma_tx_descriptor_length ) + p_conn->tx_desc_pos = 0; + } + + return desc_base; +} + +static INLINE void mailbox_oam_rx_handler(void) +{ + unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM)->vlddes; + struct rx_descriptor reg_desc; + struct uni_cell_header *header; + int conn; + struct atm_vcc *vcc; + unsigned int i; + + for ( i = 0; i < vlddes; i++ ) { + do { + reg_desc = g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos]; + } while ( reg_desc.own || !reg_desc.c ); // keep test OWN and C bit until data is ready + + header = (struct uni_cell_header *)&g_atm_priv_data.oam_buf[g_atm_priv_data.oam_desc_pos * RX_DMA_CH_OAM_BUF_SIZE]; + + if ( header->pti == ATM_PTI_SEGF5 || header->pti == ATM_PTI_E2EF5 ) + conn = find_vpivci(header->vpi, header->vci); + else if ( header->vci == 0x03 || header->vci == 0x04 ) + conn = find_vpi(header->vpi); + else + conn = -1; + + if ( conn >= 0 && g_atm_priv_data.conn[conn].vcc != NULL ) { + vcc = g_atm_priv_data.conn[conn].vcc; + + if ( vcc->push_oam != NULL ) + vcc->push_oam(vcc, header); + else + ifx_push_oam((unsigned char *)header); + adsl_led_flash(); + } + + reg_desc.byteoff = 0; + reg_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE; + reg_desc.own = 1; + reg_desc.c = 0; + + g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos] = reg_desc; + if ( ++g_atm_priv_data.oam_desc_pos == RX_DMA_CH_OAM_DESC_LEN ) + g_atm_priv_data.oam_desc_pos = 0; + + mailbox_signal(RX_DMA_CH_OAM, 0); + } +} + +static INLINE void mailbox_aal_rx_handler(void) +{ + unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL)->vlddes; + struct rx_descriptor reg_desc; + int conn; + struct atm_vcc *vcc; + struct sk_buff *skb, *new_skb; + struct rx_inband_trailer *trailer; + unsigned int i; + + for ( i = 0; i < vlddes; i++ ) { + do { + reg_desc = g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos]; + } while ( reg_desc.own || !reg_desc.c ); // keep test OWN and C bit until data is ready + + conn = reg_desc.id; + + if ( g_atm_priv_data.conn[conn].vcc != NULL ) { + vcc = g_atm_priv_data.conn[conn].vcc; + + skb = get_skb_rx_pointer(reg_desc.dataptr); + + if ( reg_desc.err ) { + if ( vcc->qos.aal == ATM_AAL5 ) { + trailer = (struct rx_inband_trailer *)((unsigned int)skb->data + ((reg_desc.byteoff + reg_desc.datalen + MAX_RX_PACKET_PADDING_BYTES) & ~MAX_RX_PACKET_PADDING_BYTES)); + if ( trailer->stw_crc ) + g_atm_priv_data.conn[conn].aal5_vcc_crc_err++; + if ( trailer->stw_ovz ) + g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu++; + g_atm_priv_data.wrx_drop_pdu++; + } + if ( vcc->stats ) { + atomic_inc(&vcc->stats->rx_drop); + atomic_inc(&vcc->stats->rx_err); + } + } + else if ( atm_charge(vcc, skb->truesize) ) { + new_skb = alloc_skb_rx(); + if ( new_skb != NULL ) { + skb_reserve(skb, reg_desc.byteoff); + skb_put(skb, reg_desc.datalen); + ATM_SKB(skb)->vcc = vcc; + + dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 0); + + vcc->push(vcc, skb); + + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wrx_pdu++; + if ( vcc->stats ) + atomic_inc(&vcc->stats->rx); + adsl_led_flash(); + + reg_desc.dataptr = (unsigned int)new_skb->data >> 2; + } + else { + atm_return(vcc, skb->truesize); + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wrx_drop_pdu++; + if ( vcc->stats ) + atomic_inc(&vcc->stats->rx_drop); + } + } + else { + if ( vcc->qos.aal == ATM_AAL5 ) + g_atm_priv_data.wrx_drop_pdu++; + if ( vcc->stats ) + atomic_inc(&vcc->stats->rx_drop); + } + } + else { + g_atm_priv_data.wrx_drop_pdu++; + } + + reg_desc.byteoff = 0; + reg_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE; + reg_desc.own = 1; + reg_desc.c = 0; + + g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos] = reg_desc; + if ( ++g_atm_priv_data.aal_desc_pos == dma_rx_descriptor_length ) + g_atm_priv_data.aal_desc_pos = 0; + + mailbox_signal(RX_DMA_CH_AAL, 0); + } +} + +#if defined(ENABLE_TASKLET) && ENABLE_TASKLET +static void do_ppe_tasklet(unsigned long arg) +{ + *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR; + mailbox_oam_rx_handler(); + mailbox_aal_rx_handler(); + if ( (*MBOX_IGU1_ISR & ((1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM))) != 0 ) + tasklet_schedule(&g_dma_tasklet); + else + enable_irq(PPE_MAILBOX_IGU1_INT); +} +#endif + +static irqreturn_t mailbox_irq_handler(int irq, void *dev_id) +{ + if ( !*MBOX_IGU1_ISR ) + return IRQ_HANDLED; + +#if defined(ENABLE_TASKLET) && ENABLE_TASKLET + disable_irq(PPE_MAILBOX_IGU1_INT); + tasklet_schedule(&g_dma_tasklet); +#else + *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR; + mailbox_oam_rx_handler(); + mailbox_aal_rx_handler(); +#endif + + return IRQ_HANDLED; +} + +static INLINE void mailbox_signal(unsigned int queue, int is_tx) +{ + int count = 1000; + + if ( is_tx ) { + while ( MBOX_IGU3_ISR_ISR(queue + FIRST_QSB_QID + 16) && count) + count--; + *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue + FIRST_QSB_QID + 16); + } + else { + while ( MBOX_IGU3_ISR_ISR(queue) && count) + count--; + *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue); + } + ASSERT(count != 0, "MBOX_IGU3_ISR = 0x%08x", ltq_r32(MBOX_IGU3_ISR)); +} + +static void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, unsigned int queue) +{ + struct clk *clk = clk_get(0, "fpi"); + unsigned int qsb_clk = clk_get_rate(clk); + unsigned int qsb_qid = queue + FIRST_QSB_QID; + union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}}; + union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}}; + unsigned int tmp; + +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) { + static char *str_traffic_class[9] = { + "ATM_NONE", + "ATM_UBR", + "ATM_CBR", + "ATM_VBR", + "ATM_ABR", + "ATM_ANYCLASS", + "ATM_VBR_RT", + "ATM_UBR_PLUS", + "ATM_MAX_PCR" + }; + printk(KERN_INFO "QoS Parameters:\n"); + printk(KERN_INFO "\tAAL : %d\n", qos->aal); + printk(KERN_INFO "\tTX Traffic Class: %s\n", str_traffic_class[qos->txtp.traffic_class]); + printk(KERN_INFO "\tTX Max PCR : %d\n", qos->txtp.max_pcr); + printk(KERN_INFO "\tTX Min PCR : %d\n", qos->txtp.min_pcr); + printk(KERN_INFO "\tTX PCR : %d\n", qos->txtp.pcr); + printk(KERN_INFO "\tTX Max CDV : %d\n", qos->txtp.max_cdv); + printk(KERN_INFO "\tTX Max SDU : %d\n", qos->txtp.max_sdu); + printk(KERN_INFO "\tTX SCR : %d\n", qos->txtp.scr); + printk(KERN_INFO "\tTX MBS : %d\n", qos->txtp.mbs); + printk(KERN_INFO "\tTX CDV : %d\n", qos->txtp.cdv); + printk(KERN_INFO "\tRX Traffic Class: %s\n", str_traffic_class[qos->rxtp.traffic_class]); + printk(KERN_INFO "\tRX Max PCR : %d\n", qos->rxtp.max_pcr); + printk(KERN_INFO "\tRX Min PCR : %d\n", qos->rxtp.min_pcr); + printk(KERN_INFO "\tRX PCR : %d\n", qos->rxtp.pcr); + printk(KERN_INFO "\tRX Max CDV : %d\n", qos->rxtp.max_cdv); + printk(KERN_INFO "\tRX Max SDU : %d\n", qos->rxtp.max_sdu); + printk(KERN_INFO "\tRX SCR : %d\n", qos->rxtp.scr); + printk(KERN_INFO "\tRX MBS : %d\n", qos->rxtp.mbs); + printk(KERN_INFO "\tRX CDV : %d\n", qos->rxtp.cdv); + } +#endif // defined(DEBUG_QOS) && DEBUG_QOS + + /* + * Peak Cell Rate (PCR) Limiter + */ + if ( qos->txtp.max_pcr == 0 ) + qsb_queue_parameter_table.bit.tp = 0; /* disable PCR limiter */ + else { + /* peak cell rate would be slightly lower than requested [maximum_rate / pcr = (qsb_clock / 8) * (time_step / 4) / pcr] */ + tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.max_pcr + 1; + /* check if overflow takes place */ + qsb_queue_parameter_table.bit.tp = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp; + } + + // A funny issue. Create two PVCs, one UBR and one UBR with max_pcr. + // Send packets to these two PVCs at same time, it trigger strange behavior. + // In A1, RAM from 0x80000000 to 0x0x8007FFFF was corrupted with fixed pattern 0x00000000 0x40000000. + // In A4, PPE firmware keep emiting unknown cell and do not respond to driver. + // To work around, create UBR always with max_pcr. + // If user want to create UBR without max_pcr, we give a default one larger than line-rate. + if ( qos->txtp.traffic_class == ATM_UBR && qsb_queue_parameter_table.bit.tp == 0 ) { + int port = g_atm_priv_data.conn[queue].port; + unsigned int max_pcr = g_atm_priv_data.port[port].tx_max_cell_rate + 1000; + + tmp = ((qsb_clk * qsb_tstep) >> 5) / max_pcr + 1; + if ( tmp > QSB_TP_TS_MAX ) + tmp = QSB_TP_TS_MAX; + else if ( tmp < 1 ) + tmp = 1; + qsb_queue_parameter_table.bit.tp = tmp; + } + + /* + * Weighted Fair Queueing Factor (WFQF) + */ + switch ( qos->txtp.traffic_class ) { + case ATM_CBR: + case ATM_VBR_RT: + /* real time queue gets weighted fair queueing bypass */ + qsb_queue_parameter_table.bit.wfqf = 0; + break; + case ATM_VBR_NRT: + case ATM_UBR_PLUS: + /* WFQF calculation here is based on virtual cell rates, to reduce granularity for high rates */ + /* WFQF is maximum cell rate / garenteed cell rate */ + /* wfqf = qsb_minimum_cell_rate * QSB_WFQ_NONUBR_MAX / requested_minimum_peak_cell_rate */ + if ( qos->txtp.min_pcr == 0 ) + qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX; + else + { + tmp = QSB_GCR_MIN * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr; + if ( tmp == 0 ) + qsb_queue_parameter_table.bit.wfqf = 1; + else if ( tmp > QSB_WFQ_NONUBR_MAX ) + qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX; + else + qsb_queue_parameter_table.bit.wfqf = tmp; + } + break; + default: + case ATM_UBR: + qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_UBR_BYPASS; + } + + /* + * Sustained Cell Rate (SCR) Leaky Bucket Shaper VBR.0/VBR.1 + */ + if ( qos->txtp.traffic_class == ATM_VBR_RT || qos->txtp.traffic_class == ATM_VBR_NRT ) { + if ( qos->txtp.scr == 0 ) { + /* disable shaper */ + qsb_queue_vbr_parameter_table.bit.taus = 0; + qsb_queue_vbr_parameter_table.bit.ts = 0; + } + else { + /* Cell Loss Priority (CLP) */ + if ( (vcc->atm_options & ATM_ATMOPT_CLP) ) + /* CLP1 */ + qsb_queue_parameter_table.bit.vbr = 1; + else + /* CLP0 */ + qsb_queue_parameter_table.bit.vbr = 0; + /* Rate Shaper Parameter (TS) and Burst Tolerance Parameter for SCR (tauS) */ + tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.scr + 1; + qsb_queue_vbr_parameter_table.bit.ts = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp; + tmp = (qos->txtp.mbs - 1) * (qsb_queue_vbr_parameter_table.bit.ts - qsb_queue_parameter_table.bit.tp) / 64; + if ( tmp == 0 ) + qsb_queue_vbr_parameter_table.bit.taus = 1; + else if ( tmp > QSB_TAUS_MAX ) + qsb_queue_vbr_parameter_table.bit.taus = QSB_TAUS_MAX; + else + qsb_queue_vbr_parameter_table.bit.taus = tmp; + } + } + else { + qsb_queue_vbr_parameter_table.bit.taus = 0; + qsb_queue_vbr_parameter_table.bit.ts = 0; + } + + /* Queue Parameter Table (QPT) */ + *QSB_RTM = QSB_RTM_DM_SET(QSB_QPT_SET_MASK); + *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword); + *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_QPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid); +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) + printk("QPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC); +#endif + /* Queue VBR Paramter Table (QVPT) */ + *QSB_RTM = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK); + *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword); + *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_VBR) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid); +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) + printk("QVPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC); +#endif + +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) { + printk("set_qsb\n"); + printk(" qsb_clk = %lu\n", (unsigned long)qsb_clk); + printk(" qsb_queue_parameter_table.bit.tp = %d\n", (int)qsb_queue_parameter_table.bit.tp); + printk(" qsb_queue_parameter_table.bit.wfqf = %d (0x%08X)\n", (int)qsb_queue_parameter_table.bit.wfqf, (int)qsb_queue_parameter_table.bit.wfqf); + printk(" qsb_queue_parameter_table.bit.vbr = %d\n", (int)qsb_queue_parameter_table.bit.vbr); + printk(" qsb_queue_parameter_table.dword = 0x%08X\n", (int)qsb_queue_parameter_table.dword); + printk(" qsb_queue_vbr_parameter_table.bit.ts = %d\n", (int)qsb_queue_vbr_parameter_table.bit.ts); + printk(" qsb_queue_vbr_parameter_table.bit.taus = %d\n", (int)qsb_queue_vbr_parameter_table.bit.taus); + printk(" qsb_queue_vbr_parameter_table.dword = 0x%08X\n", (int)qsb_queue_vbr_parameter_table.dword); + } +#endif +} + +static void qsb_global_set(void) +{ + struct clk *clk = clk_get(0, "fpi"); + unsigned int qsb_clk = clk_get_rate(clk); + int i; + unsigned int tmp1, tmp2, tmp3; + + *QSB_ICDV = QSB_ICDV_TAU_SET(qsb_tau); + *QSB_SBL = QSB_SBL_SBL_SET(qsb_srvm); + *QSB_CFG = QSB_CFG_TSTEPC_SET(qsb_tstep >> 1); +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) { + printk("qsb_clk = %u\n", qsb_clk); + printk("QSB_ICDV (%08X) = %d (%d), QSB_SBL (%08X) = %d (%d), QSB_CFG (%08X) = %d (%d)\n", (unsigned int)QSB_ICDV, *QSB_ICDV, QSB_ICDV_TAU_SET(qsb_tau), (unsigned int)QSB_SBL, *QSB_SBL, QSB_SBL_SBL_SET(qsb_srvm), (unsigned int)QSB_CFG, *QSB_CFG, QSB_CFG_TSTEPC_SET(qsb_tstep >> 1)); + } +#endif + + /* + * set SCT and SPT per port + */ + for ( i = 0; i < ATM_PORT_NUMBER; i++ ) { + if ( g_atm_priv_data.port[i].tx_max_cell_rate != 0 ) { + tmp1 = ((qsb_clk * qsb_tstep) >> 1) / g_atm_priv_data.port[i].tx_max_cell_rate; + tmp2 = tmp1 >> 6; /* integer value of Tsb */ + tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */ + /* carry over to integer part (?) */ + if ( tmp3 == (1 << 6) ) + { + tmp3 = 0; + tmp2++; + } + if ( tmp2 == 0 ) + tmp2 = tmp3 = 1; + /* 1. set mask */ + /* 2. write value to data transfer register */ + /* 3. start the tranfer */ + /* SCT (FracRate) */ + *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK); + *QSB_RTD = QSB_RTD_TTV_SET(tmp3); + *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) + printk("SCT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC); +#endif + /* SPT (SBV + PN + IntRage) */ + *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK); + *QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2)); + *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); +#if defined(DEBUG_QOS) && DEBUG_QOS + if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) + printk("SPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC); +#endif + } + } +} + +static INLINE void set_htu_entry(unsigned int vpi, unsigned int vci, unsigned int queue, int aal5, int is_retx) +{ + struct htu_entry htu_entry = { res1: 0x00, + clp: is_retx ? 0x01 : 0x00, + pid: g_atm_priv_data.conn[queue].port & 0x01, + vpi: vpi, + vci: vci, + pti: 0x00, + vld: 0x01}; + + struct htu_mask htu_mask = { set: 0x01, +#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX + clp: 0x01, + pid_mask: 0x02, +#else + clp: g_retx_htu ? 0x00 : 0x01, + pid_mask: RETX_MODE_CFG->retx_en ? 0x03 : 0x02, +#endif + vpi_mask: 0x00, +#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX + vci_mask: 0x0000, +#else + vci_mask: RETX_MODE_CFG->retx_en ? 0xFF00 : 0x0000, +#endif + pti_mask: 0x03, // 0xx, user data + clear: 0x00}; + + struct htu_result htu_result = {res1: 0x00, + cellid: queue, + res2: 0x00, + type: aal5 ? 0x00 : 0x01, + ven: 0x01, + res3: 0x00, + qid: queue}; + + *HTU_RESULT(queue + OAM_HTU_ENTRY_NUMBER) = htu_result; + *HTU_MASK(queue + OAM_HTU_ENTRY_NUMBER) = htu_mask; + *HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER) = htu_entry; +} + +static INLINE void clear_htu_entry(unsigned int queue) +{ + HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER)->vld = 0; +} + +static void validate_oam_htu_entry(void) +{ + HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 1; + HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 1; + HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 1; +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 1; +#endif +} + +static void invalidate_oam_htu_entry(void) +{ + HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 0; + HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 0; + HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 0; +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 0; +#endif +} + +static INLINE int find_vpi(unsigned int vpi) +{ + int i; + unsigned int bit; + + for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) { + if ( (g_atm_priv_data.conn_table & bit) != 0 + && g_atm_priv_data.conn[i].vcc != NULL + && vpi == g_atm_priv_data.conn[i].vcc->vpi ) + return i; + } + + return -1; +} + +static INLINE int find_vpivci(unsigned int vpi, unsigned int vci) +{ + int i; + unsigned int bit; + + for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) { + if ( (g_atm_priv_data.conn_table & bit) != 0 + && g_atm_priv_data.conn[i].vcc != NULL + && vpi == g_atm_priv_data.conn[i].vcc->vpi + && vci == g_atm_priv_data.conn[i].vcc->vci ) + return i; + } + + return -1; +} + +static INLINE int find_vcc(struct atm_vcc *vcc) +{ + int i; + unsigned int bit; + + for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) { + if ( (g_atm_priv_data.conn_table & bit) != 0 + && g_atm_priv_data.conn[i].vcc == vcc ) + return i; + } + + return -1; +} + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + +static void retx_polling_func(unsigned long arg) +{ + int sys_flag; + volatile struct dsl_param *p_dsl_param; + int new_retx_htu; + int retx_en; + int i, max_htu; + + local_irq_save(sys_flag); + if ( g_retx_playout_buffer == 0 && g_xdata_addr != NULL && (((volatile struct dsl_param *)g_xdata_addr)->RetxEnable || ((volatile struct dsl_param *)g_xdata_addr)->ServiceSpecificReTx) ) { + local_irq_restore(sys_flag); + g_retx_playout_buffer = __get_free_pages(GFP_KERNEL, RETX_PLAYOUT_BUFFER_ORDER); + if ( g_retx_playout_buffer == 0 ) + panic("no memory for g_retx_playout_buffer\n"); + memset((void *)g_retx_playout_buffer, 0, RETX_PLAYOUT_BUFFER_SIZE); + dma_cache_inv(g_retx_playout_buffer, RETX_PLAYOUT_BUFFER_SIZE); + } + else + local_irq_restore(sys_flag); + + + local_irq_save(sys_flag); + if ( g_xdata_addr != NULL ) { + p_dsl_param = (volatile struct dsl_param *)g_xdata_addr; + g_retx_polling_cnt += RETX_POLLING_INTERVAL; + + if ( p_dsl_param->update_flag ) { + do_gettimeofday(&g_retx_polling_start); + + g_dsl_param = *p_dsl_param; + + // we always enable retx (just for test purpose) + //g_dsl_param.RetxEnable = 1; + //RETX_TSYNC_CFG->fw_alpha = 0; + + if ( g_dsl_param.RetxEnable || g_dsl_param.ServiceSpecificReTx ) { + // ReTX enabled + // MIB counter updated for each polling + p_dsl_param->RxDtuCorruptedCNT = *RxDTUCorruptedCNT; + p_dsl_param->RxRetxDtuUnCorrectedCNT = *RxRetxDTUUncorrectedCNT; + p_dsl_param->RxLastEFB = *RxLastEFBCNT; + p_dsl_param->RxDtuCorrectedCNT = *RxDTUCorrectedCNT; + + // for RETX paramters, we check only once for every second + if ( g_retx_polling_cnt < HZ ) + goto _clear_update_flag; + + g_retx_polling_cnt -= HZ; + + if ( g_dsl_param.ServiceSpecificReTx && g_dsl_param.ReTxPVC == 0 ) + new_retx_htu = 1; + else + new_retx_htu = 0; + + // default fw_alpha equals to default hardware alpha + RETX_TSYNC_CFG->fw_alpha = 0; + + RETX_TD_CFG->td_max = g_dsl_param.MaxDelayrt; + RETX_TD_CFG->td_min = g_dsl_param.MinDelayrt; + + *RETX_PLAYOUT_BUFFER_BASE = ((((unsigned int)g_retx_playout_buffer | KSEG1) + 15) & 0xFFFFFFF0) >> 2; + + if ( g_dsl_param.ServiceSpecificReTx ) { + *RETX_SERVICE_HEADER_CFG= g_dsl_param.ReTxPVC << 4; + if ( g_dsl_param.ReTxPVC == 0 ) + *RETX_MASK_HEADER_CFG = 1; + else + *RETX_MASK_HEADER_CFG = 0; + } + else { + *RETX_SERVICE_HEADER_CFG= 0; + *RETX_MASK_HEADER_CFG = 0; + } + + retx_en = 1; + } + else { + // ReTX disabled + + new_retx_htu = 0; + + RETX_TSYNC_CFG->fw_alpha = 7; + + *RETX_SERVICE_HEADER_CFG = 0; + *RETX_MASK_HEADER_CFG = 0; + + retx_en = 0; + } + + + if ( retx_en != RETX_MODE_CFG->retx_en ) { + unsigned int pid_mask, vci_mask; + + if ( retx_en ) { + pid_mask = 0x03; + vci_mask = 0xFF00; + } + else { + pid_mask = 0x02; + vci_mask = 0x0000; + } + + max_htu = *CFG_WRX_HTUTS; + for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ ) + if ( HTU_ENTRY(i)->vld ) { + HTU_MASK(i)->pid_mask = pid_mask; + HTU_MASK(i)->vci_mask = vci_mask; + } + } + + if ( new_retx_htu != g_retx_htu ) { + int conn, retx_conn; + + g_retx_htu = new_retx_htu; + + if ( g_retx_htu ) { + max_htu = *CFG_WRX_HTUTS; + for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ ) + if ( HTU_ENTRY(i)->vld ) + HTU_MASK(i)->clp = 0; + + for ( conn = 0; conn < MAX_PVC_NUMBER; conn++ ) + if ( g_atm_priv_data.conn[conn].vcc && g_atm_priv_data.conn[conn].vcc->qos.aal == ATM_AAL5 && !HTU_ENTRY(conn + OAM_HTU_ENTRY_NUMBER)->clp ) { + retx_conn = (conn + 8) % 16; // ReTX queue + + if ( retx_conn < MAX_PVC_NUMBER && test_and_set_bit(retx_conn, &g_atm_priv_data.conn_table) == 0 ) { + g_atm_priv_data.conn[retx_conn].vcc = g_atm_priv_data.conn[conn].vcc; + set_htu_entry(g_atm_priv_data.conn[conn].vcc->vpi, g_atm_priv_data.conn[conn].vcc->vci, retx_conn, g_atm_priv_data.conn[conn].vcc->qos.aal == ATM_AAL5 ? 1 : 0, 1); + } + else { + err("Queue number %d for ReTX queue of PVC(%d.%d) is not available!", retx_conn, g_atm_priv_data.conn[conn].vcc->vpi, g_atm_priv_data.conn[conn].vcc->vci); + } + } + } + else + { + for ( retx_conn = 0; retx_conn < MAX_PVC_NUMBER; retx_conn++ ) + if ( g_atm_priv_data.conn[retx_conn].vcc && HTU_ENTRY(retx_conn + OAM_HTU_ENTRY_NUMBER)->clp ) { + clear_htu_entry(retx_conn); + g_atm_priv_data.conn[retx_conn].vcc = NULL; + g_atm_priv_data.conn[retx_conn].aal5_vcc_crc_err = 0; + g_atm_priv_data.conn[retx_conn].aal5_vcc_oversize_sdu = 0; + clear_bit(retx_conn, &g_atm_priv_data.conn_table); + } + + max_htu = *CFG_WRX_HTUTS; + for ( i = OAM_HTU_ENTRY_NUMBER; i < max_htu; i++ ) + if ( HTU_ENTRY(i)->vld ) + HTU_MASK(i)->clp = 1; + } + } + + RETX_MODE_CFG->retx_en = retx_en; + +_clear_update_flag: + p_dsl_param->update_flag = 0; + + do_gettimeofday(&g_retx_polling_end); + } + + g_retx_polling_timer.expires = jiffies + RETX_POLLING_INTERVAL; + add_timer(&g_retx_polling_timer); + } + local_irq_restore(sys_flag); +} + +static int init_atm_tc_retrans_param(void) +{ + int i = 0; + struct DTU_stat_info reset_val; + + RETX_MODE_CFG->invld_range = 128; + RETX_MODE_CFG->buff_size = RETX_PLAYOUT_FW_BUFF_SIZE > 4096/32 ? 4096/32 : RETX_PLAYOUT_FW_BUFF_SIZE ; + RETX_MODE_CFG->retx_en = 1; + + // default fw_alpha equals to default hardware alpha + RETX_TSYNC_CFG->fw_alpha = 7; + RETX_TSYNC_CFG->sync_inp = 0; + + RETX_TD_CFG->td_max = 0; + RETX_TD_CFG->td_min = 0; + + // *RETX_PLAYOUT_BUFFER_BASE = KSEG1ADDR(g_retx_playout_buffer); // need " >> 2 " ? + *RETX_PLAYOUT_BUFFER_BASE = ((((unsigned int)g_retx_playout_buffer | KSEG1) + 15) & 0xFFFFFFF0) >> 2; + + *RETX_SERVICE_HEADER_CFG = 0; + *RETX_MASK_HEADER_CFG = 0; + + // 20us + RETX_MIB_TIMER_CFG->tick_cycle = 4800; + RETX_MIB_TIMER_CFG->ticks_per_sec = 50000; + + *LAST_DTU_SID_IN = 255; + *RFBI_FIRST_CW = 1; + // init DTU_STAT_INFO + + memset(&reset_val, 0, sizeof(reset_val)); + reset_val.dtu_rd_ptr = reset_val.dtu_wr_ptr = 0xffff; + + for(i = 0 ; i < 256; i ++) { + DTU_STAT_INFO[i] = reset_val; + } + return 0; +} + +static void clear_atm_tc_retrans_param(void) +{ + if ( g_retx_playout_buffer ) { + free_pages(g_retx_playout_buffer, RETX_PLAYOUT_BUFFER_ORDER); + g_retx_playout_buffer = 0; + } +} + +#endif + +#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB +static void dump_skb(struct sk_buff *skb, unsigned int len, char *title, int port, int ch, int is_tx) +{ + int i; + + if ( !(ifx_atm_dbg_enable & (is_tx ? DBG_ENABLE_MASK_DUMP_SKB_TX : DBG_ENABLE_MASK_DUMP_SKB_RX)) ) + return; + + if ( skb->len < len ) + len = skb->len; + + if ( len > RX_DMA_CH_AAL_BUF_SIZE ) { + printk("too big data length: skb = %08x, skb->data = %08x, skb->len = %d\n", (unsigned int)skb, (unsigned int)skb->data, skb->len); + return; + } + + if ( ch >= 0 ) + printk("%s (port %d, ch %d)\n", title, port, ch); + else + printk("%s\n", title); + printk(" skb->data = %08X, skb->tail = %08X, skb->len = %d\n", (unsigned int)skb->data, (unsigned int)skb->tail, (int)skb->len); + for ( i = 1; i <= len; i++ ) { + if ( i % 16 == 1 ) + printk(" %4d:", i - 1); + printk(" %02X", (int)(*((char*)skb->data + i - 1) & 0xFF)); + if ( i % 16 == 0 ) + printk("\n"); + } + if ( (i - 1) % 16 != 0 ) + printk("\n"); +} +#endif + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC +static void skb_swap(struct sk_buff *skb, unsigned int byteoff) +{ + unsigned int mac_offset = ~0; + unsigned int ip_offset = ~0; + unsigned char tmp[8]; + unsigned char *p = NULL; + + skb_pull(skb, byteoff + TX_INBAND_HEADER_LENGTH); + + if ( skb->data[0] == 0xAA && skb->data[1] == 0xAA && skb->data[2] == 0x03 ) { + // LLC + if ( skb->data[3] == 0x00 && skb->data[4] == 0x80 && skb->data[5] == 0xC2 ) { + // EoA + if ( skb->data[22] == 0x08 && skb->data[23] == 0x00 ) { + // IPv4 + mac_offset = 10; + ip_offset = 24; + } + else if ( skb->data[31] == 0x21 ) { + // PPPoE IPv4 + mac_offset = 10; + ip_offset = 32; + } + } + else { + // IPoA + if ( skb->data[6] == 0x08 && skb->data[7] == 0x00 ) { + // IPv4 + ip_offset = 8; + } + } + } + else if ( skb->data[0] == 0xFE && skb->data[1] == 0xFE && skb->data[2] == 0x03 ) { + // LLC PPPoA + if ( skb->data[4] == 0x00 && skb->data[5] == 0x21 ) { + // IPv4 + ip_offset = 6; + } + } + else { + // VC-mux + if ( skb->data[0] == 0x00 && skb->data[1] == 0x21 ) { + // PPPoA IPv4 + ip_offset = 2; + } + else if ( skb->data[0] == 0x00 && skb->data[1] == 0x00 ) { + // EoA + if ( skb->data[14] == 0x08 && skb->data[15] ==0x00 ) { + // IPv4 + mac_offset = 2; + ip_offset = 16; + } + else if ( skb->data[23] == 0x21 ) { + // PPPoE IPv4 + mac_offset = 2; + ip_offset = 26; + } + } + else { + // IPoA + ip_offset = 0; + } + } + + if ( mac_offset != ~0 && !(skb->data[mac_offset] & 0x01) ) { + p = skb->data + mac_offset; + // swap MAC + memcpy(tmp, p, 6); + memcpy(p, p + 6, 6); + memcpy(p + 6, tmp, 6); + p += 12; + } + + if ( ip_offset != ~0 ) { + p = skb->data + ip_offset + 12; + // swap IP + memcpy(tmp, p, 4); + memcpy(p, p + 4, 4); + memcpy(p + 4, tmp, 4); + p += 8; + } + + if ( p != NULL ) { + dma_cache_wback((unsigned long)skb->data, (unsigned long)p - (unsigned long)skb->data); + } + + skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH); +} +#endif + +static INLINE void proc_file_create(void) +{ + struct proc_dir_entry *res; + + g_atm_dir = proc_mkdir("driver/ifx_atm", NULL); + + create_proc_read_entry("version", + 0, + g_atm_dir, + proc_read_version, + NULL); + + res = create_proc_entry("mib", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_mib; + res->write_proc = proc_write_mib; + } + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + res = create_proc_entry("retx_mib", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_retx_mib; + res->write_proc = proc_write_retx_mib; + } +#endif + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + res = create_proc_entry("dbg", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_dbg; + res->write_proc = proc_write_dbg; + } + + res = create_proc_entry("mem", + 0, + g_atm_dir); + if ( res != NULL ) + res->write_proc = proc_write_mem; + + #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE) + res = create_proc_entry("pp32", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_pp32; + res->write_proc = proc_write_pp32; + } + #endif +#endif + +#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC + create_proc_read_entry("htu", + 0, + g_atm_dir, + proc_read_htu, + NULL); + + create_proc_read_entry("txq", + 0, + g_atm_dir, + proc_read_txq, + NULL); + + #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + create_proc_read_entry("retx_fw", + 0, + g_atm_dir, + proc_read_retx_fw, + NULL); + + res = create_proc_entry("retx_stats", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_retx_stats; + res->write_proc = proc_write_retx_stats; + } + + res = create_proc_entry("retx_cfg", + 0, + g_atm_dir); + if ( res != NULL ) { + res->read_proc = proc_read_retx_cfg; + res->write_proc = proc_write_retx_cfg; + } + + create_proc_read_entry("retx_dsl_param", + 0, + g_atm_dir, + proc_read_retx_dsl_param, + NULL); + #endif +#endif +} + +static INLINE void proc_file_delete(void) +{ +#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC + #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + remove_proc_entry("retx_dsl_param", g_atm_dir); + + remove_proc_entry("retx_cfg", g_atm_dir); + + remove_proc_entry("retx_stats", g_atm_dir); + + remove_proc_entry("retx_fw", g_atm_dir); + #endif + + remove_proc_entry("txq", g_atm_dir); + + remove_proc_entry("htu", g_atm_dir); +#endif + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + #if defined(CONFIG_AR9) || defined(CONFIG_VR9) || defined(CONFIG_DANUBE) || defined(CONFIG_AMAZON_SE) + remove_proc_entry("pp32", g_atm_dir); + #endif + + remove_proc_entry("mem", g_atm_dir); + + remove_proc_entry("dbg", g_atm_dir); +#endif + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + remove_proc_entry("retx_mib", g_atm_dir); +#endif + + remove_proc_entry("mib", g_atm_dir); + + remove_proc_entry("version", g_atm_dir); + + remove_proc_entry("driver/ifx_atm", NULL); +} + +static int proc_read_version(char *buf, char **start, off_t offset, int count, int *eof, void *data) +{ + int len = 0; + + len += ifx_atm_version(buf + len); + + if ( offset >= len ) { + *start = buf; + *eof = 1; + return 0; + } + *start = buf + offset; + if ( (len -= offset) > count ) + return count; + *eof = 1; + return len; +} + +static int proc_read_mib(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page + off + len, "Firmware\n"); + len += sprintf(page + off + len, " wrx_drophtu_cell = %u\n", WAN_MIB_TABLE->wrx_drophtu_cell); + len += sprintf(page + off + len, " wrx_dropdes_pdu = %u\n", WAN_MIB_TABLE->wrx_dropdes_pdu); + len += sprintf(page + off + len, " wrx_correct_pdu = %u\n", WAN_MIB_TABLE->wrx_correct_pdu); + len += sprintf(page + off + len, " wrx_err_pdu = %u\n", WAN_MIB_TABLE->wrx_err_pdu); + len += sprintf(page + off + len, " wrx_dropdes_cell = %u\n", WAN_MIB_TABLE->wrx_dropdes_cell); + len += sprintf(page + off + len, " wrx_correct_cell = %u\n", WAN_MIB_TABLE->wrx_correct_cell); + len += sprintf(page + off + len, " wrx_err_cell = %u\n", WAN_MIB_TABLE->wrx_err_cell); + len += sprintf(page + off + len, " wrx_total_byte = %u\n", WAN_MIB_TABLE->wrx_total_byte); + len += sprintf(page + off + len, " wtx_total_pdu = %u\n", WAN_MIB_TABLE->wtx_total_pdu); + len += sprintf(page + off + len, " wtx_total_cell = %u\n", WAN_MIB_TABLE->wtx_total_cell); + len += sprintf(page + off + len, " wtx_total_byte = %u\n", WAN_MIB_TABLE->wtx_total_byte); + len += sprintf(page + off + len, "Driver\n"); + len += sprintf(page + off + len, " wrx_pdu = %u\n", g_atm_priv_data.wrx_pdu); + len += sprintf(page + off + len, " wrx_drop_pdu = %u\n", g_atm_priv_data.wrx_drop_pdu); + len += sprintf(page + off + len, " wtx_pdu = %u\n", g_atm_priv_data.wtx_pdu); + len += sprintf(page + off + len, " wtx_err_pdu = %u\n", g_atm_priv_data.wtx_err_pdu); + len += sprintf(page + off + len, " wtx_drop_pdu = %u\n", g_atm_priv_data.wtx_drop_pdu); + + *eof = 1; + + return len; +} + +static int proc_write_mib(struct file *file, const char *buf, unsigned long count, void *data) +{ + char str[1024]; + char *p; + int len, rlen; + + len = count < sizeof(str) ? count : sizeof(str) - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ) + return 0; + + if ( stricmp(p, "clear") == 0 || stricmp(p, "clear all") == 0 + || stricmp(p, "clean") == 0 || stricmp(p, "clean all") == 0 ) { + memset(WAN_MIB_TABLE, 0, sizeof(*WAN_MIB_TABLE)); + g_atm_priv_data.wrx_pdu = 0; + g_atm_priv_data.wrx_drop_pdu = 0; + g_atm_priv_data.wtx_pdu = 0; + g_atm_priv_data.wtx_err_pdu = 0; + g_atm_priv_data.wtx_drop_pdu = 0; + } + + return count; +} + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + +static int proc_read_retx_mib(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + printk("Retx FW DTU MIB :\n"); + printk(" rx_total_dtu = %u\n", *URETX_RX_TOTAL_DTU); + printk(" rx_bad_dtu = %u\n", *URETX_RX_BAD_DTU); + printk(" rx_good_dtu = %u\n", *URETX_RX_GOOD_DTU); + printk(" rx_corrected_dtu = %u\n", *URETX_RX_CORRECTED_DTU); + printk(" rx_outofdate_dtu = %u\n", *URETX_RX_OUTOFDATE_DTU); + printk(" rx_duplicate_dtu = %u\n", *URETX_RX_DUPLICATE_DTU); + printk(" rx_timeout_dtu = %u\n", *URETX_RX_TIMEOUT_DTU); + printk(" RxDTURetransmittedCNT = %u\n", *RxDTURetransmittedCNT); + printk("\n"); + + printk("Retx Standard DTU MIB:\n"); + printk(" RxLastEFB = %u\n", *RxLastEFBCNT); + printk(" RxDTUCorrectedCNT = %u\n", *RxDTUCorrectedCNT); + printk(" RxDTUCorruptedCNT = %u\n", *RxDTUCorruptedCNT); + printk(" RxRetxDTUUncorrectedCNT = %u\n", *RxRetxDTUUncorrectedCNT); + printk("\n"); + + printk("Retx FW Cell MIB :\n"); + printk(" bc0_total_cell = %u\n", *WRX_BC0_CELL_NUM); + printk(" bc0_drop_cell = %u\n", *WRX_BC0_DROP_CELL_NUM); + printk(" bc0_nonretx_cell = %u\n", *WRX_BC0_NONRETX_CELL_NUM); + printk(" bc0_retx_cell = %u\n", *WRX_BC0_RETX_CELL_NUM); + printk(" bc0_outofdate_cell = %u\n", *WRX_BC0_OUTOFDATE_CELL_NUM); + printk(" bc0_directup_cell = %u\n", *WRX_BC0_DIRECTUP_NUM); + printk(" bc0_to_pb_total_cell = %u\n", *WRX_BC0_PBW_TOTAL_NUM); + printk(" bc0_to_pb_succ_cell = %u\n", *WRX_BC0_PBW_SUCC_NUM); + printk(" bc0_to_pb_fail_cell = %u\n", *WRX_BC0_PBW_FAIL_NUM); + printk(" bc1_total_cell = %u\n", *WRX_BC1_CELL_NUM); + + printk("\n"); + + printk("ATM Rx AAL5/OAM MIB:\n"); + printk(" wrx_drophtu_cell = %u\n", WAN_MIB_TABLE->wrx_drophtu_cell); + printk(" wrx_dropdes_pdu = %u\n", WAN_MIB_TABLE->wrx_dropdes_pdu); + + printk(" wrx_correct_pdu = %-10u ", WAN_MIB_TABLE->wrx_correct_pdu); + if ( WAN_MIB_TABLE->wrx_correct_pdu == 0 ) + printk("\n"); + else { + int i = 0; + + printk("[ "); + for ( i = 0; i < 16; ++i ) { + if ( WRX_PER_PVC_CORRECT_PDU_BASE[i] ) + printk("q%-2d = %-10u , ", i, WRX_PER_PVC_CORRECT_PDU_BASE[i]); + } + printk("]\n"); + } + + printk(" wrx_err_pdu = %-10u ", WAN_MIB_TABLE->wrx_err_pdu); + if ( WAN_MIB_TABLE->wrx_err_pdu == 0 ) + printk("\n"); + else { + int i = 0; + + printk("[ "); + for ( i = 0; i < 16; ++i ) { + if ( WRX_PER_PVC_ERROR_PDU_BASE[i] ) + printk("q%-2d = %-10u , ", i, WRX_PER_PVC_ERROR_PDU_BASE[i] ); + } + printk("]\n"); + } + + printk(" wrx_dropdes_cell = %u\n", WAN_MIB_TABLE->wrx_dropdes_cell); + printk(" wrx_correct_cell = %u\n", WAN_MIB_TABLE->wrx_correct_cell); + printk(" wrx_err_cell = %u\n", WAN_MIB_TABLE->wrx_err_cell); + printk(" wrx_total_byte = %u\n", WAN_MIB_TABLE->wrx_total_byte); + printk("\n"); + + printk("ATM Tx MIB:\n"); + printk(" wtx_total_pdu = %u\n", WAN_MIB_TABLE->wtx_total_pdu); + printk(" wtx_total_cell = %u\n", WAN_MIB_TABLE->wtx_total_cell); + printk(" wtx_total_byte = %u\n", WAN_MIB_TABLE->wtx_total_byte); + printk("\n"); + + printk("Debugging Info:\n"); + printk(" Firmware version = %d.%d.%d.%d.%d.%d\n", + (int)FW_VER_ID->family, (int)FW_VER_ID->fwtype, (int)FW_VER_ID->interface, + (int)FW_VER_ID->fwmode, (int)FW_VER_ID->major, (int)FW_VER_ID->minor); + + printk(" retx_alpha_switch_to_hunt_times = %u\n", *URETX_ALPHA_SWITCH_TO_HUNT_TIMES); + + printk("\n"); + + *eof = 1; + + return len; +} + +static int proc_write_retx_mib(struct file *file, const char *buf, unsigned long count, void *data) +{ + char str[2048]; + char *p; + int len, rlen; + int i; + + len = count < sizeof(str) ? count : sizeof(str) - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ) + return 0; + + if ( stricmp(p, "clean") == 0 || stricmp(p, "clear") == 0 || stricmp(p, "clear_all") == 0) { + *URETX_RX_TOTAL_DTU = 0; + *URETX_RX_BAD_DTU = 0; + *URETX_RX_GOOD_DTU = 0; + *URETX_RX_CORRECTED_DTU = 0; + *URETX_RX_OUTOFDATE_DTU = 0; + *URETX_RX_DUPLICATE_DTU = 0; + *URETX_RX_TIMEOUT_DTU = 0; + *RxDTURetransmittedCNT = 0; + + *WRX_BC0_CELL_NUM = 0; + *WRX_BC0_DROP_CELL_NUM = 0; + *WRX_BC0_NONRETX_CELL_NUM = 0; + *WRX_BC0_RETX_CELL_NUM = 0; + *WRX_BC0_OUTOFDATE_CELL_NUM = 0; + *WRX_BC0_DIRECTUP_NUM = 0; + *WRX_BC0_PBW_TOTAL_NUM = 0; + *WRX_BC0_PBW_SUCC_NUM = 0; + *WRX_BC0_PBW_FAIL_NUM = 0; + *WRX_BC1_CELL_NUM = 0; + + for ( i = 0; i < 16; ++i ) { + WRX_PER_PVC_CORRECT_PDU_BASE[i] = 0; + WRX_PER_PVC_ERROR_PDU_BASE[i] = 0; + } + + WAN_MIB_TABLE->wrx_drophtu_cell = 0; + WAN_MIB_TABLE->wrx_dropdes_pdu = 0; + WAN_MIB_TABLE->wrx_correct_pdu = 0; + WAN_MIB_TABLE->wrx_err_pdu = 0; + WAN_MIB_TABLE->wrx_dropdes_cell = 0; + WAN_MIB_TABLE->wrx_correct_cell = 0; + WAN_MIB_TABLE->wrx_err_cell = 0; + WAN_MIB_TABLE->wrx_total_byte = 0; + + WAN_MIB_TABLE->wtx_total_pdu = 0; + WAN_MIB_TABLE->wtx_total_cell = 0; + WAN_MIB_TABLE->wtx_total_byte = 0; + + *URETX_ALPHA_SWITCH_TO_HUNT_TIMES = 0; + + if (stricmp(p, "clear_all") == 0) { + *RxLastEFBCNT = 0; + *RxDTUCorrectedCNT = 0; + *RxDTUCorruptedCNT = 0; + *RxRetxDTUUncorrectedCNT = 0; + } + } + + return count; +} + +#endif + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + +static int proc_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page + off + len, "error print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "debug print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "assert - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "dump rx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_RX) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "dump tx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_TX) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "qos - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "dump init - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_INIT) ? "enabled" : "disabled"); + len += sprintf(page + off + len, "mac swap - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_MAC_SWAP) ? "enabled" : "disabled"); + + *eof = 1; + + return len; +} + +static int proc_write_dbg(struct file *file, const char *buf, unsigned long count, void *data) +{ + static const char *dbg_enable_mask_str[] = { + " error print", + " err", + " debug print", + " dbg", + " assert", + " assert", + " dump rx skb", + " rx", + " dump tx skb", + " tx", + " dump qos", + " qos", + " dump init", + " init", + " mac swap", + " swap", + " all" + }; + static const int dbg_enable_mask_str_len[] = { + 12, 4, + 12, 4, + 7, 7, + 12, 3, + 12, 3, + 9, 4, + 10, 5, + 9, 5, + 4 + }; + unsigned int dbg_enable_mask[] = { + DBG_ENABLE_MASK_ERR, + DBG_ENABLE_MASK_DEBUG_PRINT, + DBG_ENABLE_MASK_ASSERT, + DBG_ENABLE_MASK_DUMP_SKB_RX, + DBG_ENABLE_MASK_DUMP_SKB_TX, + DBG_ENABLE_MASK_DUMP_QOS, + DBG_ENABLE_MASK_DUMP_INIT, + DBG_ENABLE_MASK_MAC_SWAP, + DBG_ENABLE_MASK_ALL + }; + + char *str; + int str_buff_len = 1024; + char *p; + + int len, rlen; + + int f_enable = 0; + int i; + + str = vmalloc(str_buff_len); + if(!str){ + return 0; + } + + len = count < str_buff_len ? count : str_buff_len - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ){ + vfree(str); + return 0; + } + + if ( strincmp(p, "enable", 6) == 0 ) { + p += 6; + f_enable = 1; + } + else if ( strincmp(p, "disable", 7) == 0 ) { + p += 7; + f_enable = -1; + } + else if ( strincmp(p, "help", 4) == 0 || *p == '?' ) { + printk("echo <enable/disable> [err/dbg/assert/rx/tx/init/all] > /proc/eth/dbg\n"); + } + + if ( f_enable ) { + if ( *p == 0 ) { + if ( f_enable > 0 ) + ifx_atm_dbg_enable |= DBG_ENABLE_MASK_ALL & ~DBG_ENABLE_MASK_MAC_SWAP; + else + ifx_atm_dbg_enable &= ~DBG_ENABLE_MASK_ALL | DBG_ENABLE_MASK_MAC_SWAP; + } + else { + do { + for ( i = 0; i < NUM_ENTITY(dbg_enable_mask_str); i++ ) + if ( strincmp(p, dbg_enable_mask_str[i], dbg_enable_mask_str_len[i]) == 0 ) { + if ( f_enable > 0 ) + ifx_atm_dbg_enable |= dbg_enable_mask[i >> 1]; + else + ifx_atm_dbg_enable &= ~dbg_enable_mask[i >> 1]; + p += dbg_enable_mask_str_len[i]; + break; + } + } while ( i < NUM_ENTITY(dbg_enable_mask_str) ); + } + } + + vfree(str); + return count; +} + +static inline unsigned long sb_addr_to_fpi_addr_convert(unsigned long sb_addr) +{ + #define PP32_SB_ADDR_END 0xFFFF + + if ( sb_addr < PP32_SB_ADDR_END ) + return (unsigned long)SB_BUFFER(sb_addr); + else + return sb_addr; +} + +static int proc_write_mem(struct file *file, const char *buf, unsigned long count, void *data) +{ + char *p1, *p2; + int len; + int colon; + unsigned long *p; + int i, n, l; + int local_buf_size = 1024; + char *local_buf = NULL; + + local_buf = vmalloc(local_buf_size); + if ( !local_buf ){ + return 0; + } + + len = local_buf_size < count ? local_buf_size - 1 : count; + len = len - copy_from_user(local_buf, buf, len); + local_buf[len] = 0; + + p1 = local_buf; + colon = 1; + while ( get_token(&p1, &p2, &len, &colon) ) { + if ( stricmp(p1, "w") == 0 || stricmp(p1, "write") == 0 || stricmp(p1, "r") == 0 || stricmp(p1, "read") == 0 ) + break; + + p1 = p2; + colon = 1; + } + + if ( *p1 == 'w' ) { + ignore_space(&p2, &len); + p = (unsigned long *)get_number(&p2, &len, 1); + p = (unsigned long *)sb_addr_to_fpi_addr_convert((unsigned long)p); + + if ( (unsigned int)p >= KSEG0 ) + while ( 1 ) { + ignore_space(&p2, &len); + if ( !len || !((*p2 >= '0' && *p2 <= '9') || (*p2 >= 'a' && *p2 <= 'f') || (*p2 >= 'A' && *p2 <= 'F')) ) + break; + + *p++ = (unsigned int)get_number(&p2, &len, 1); + } + } + else if ( *p1 == 'r' ) { + ignore_space(&p2, &len); + p = (unsigned long *)get_number(&p2, &len, 1); + p = (unsigned long *)sb_addr_to_fpi_addr_convert((unsigned long)p); + + if ( (unsigned int)p >= KSEG0 ) { + ignore_space(&p2, &len); + n = (int)get_number(&p2, &len, 0); + if ( n ) { + char str[32] = {0}; + char *pch = str; + int k; + unsigned int data; + char c; + + n += (l = ((int)p >> 2) & 0x03); + p = (unsigned long *)((unsigned int)p & ~0x0F); + for ( i = 0; i < n; i++ ) { + if ( (i & 0x03) == 0 ) { + printk("%08X:", (unsigned int)p); + pch = str; + } + if ( i < l ) { + printk(" "); + sprintf(pch, " "); + } + else { + data = (unsigned int)*p; + printk(" %08X", data); + for ( k = 0; k < 4; k++ ) { + c = ((char*)&data)[k]; + pch[k] = c < ' ' ? '.' : c; + } + } + p++; + pch += 4; + if ( (i & 0x03) == 0x03 ) { + pch[0] = 0; + printk(" ; %s\n", str); + } + } + if ( (n & 0x03) != 0x00 ) { + for ( k = 4 - (n & 0x03); k > 0; k-- ) + printk(" "); + pch[0] = 0; + printk(" ; %s\n", str); + } + } + } + } + + vfree(local_buf); + return count; +} + + #if defined(CONFIG_AR9) || defined(CONFIG_VR9) + +static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + static const char *stron = " on"; + static const char *stroff = "off"; + + int len = 0; + int cur_context; + int f_stopped; + char str[256]; + char strlength; + int i, j; + + int pp32; + + for ( pp32 = 0; pp32 < NUM_OF_PP32; pp32++ ) { + f_stopped = 0; + + len += sprintf(page + off + len, "===== pp32 core %d =====\n", pp32); + + #ifdef CONFIG_VR9 + if ( (*PP32_FREEZE & (1 << (pp32 << 4))) != 0 ) { + sprintf(str, "freezed"); + f_stopped = 1; + } + #else + if ( 0 ) { + } + #endif + else if ( PP32_CPU_USER_STOPPED(pp32) || PP32_CPU_USER_BREAKIN_RCV(pp32) || PP32_CPU_USER_BREAKPOINT_MET(pp32) ) { + strlength = 0; + if ( PP32_CPU_USER_STOPPED(pp32) ) + strlength += sprintf(str + strlength, "stopped"); + if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) ) + strlength += sprintf(str + strlength, strlength ? " | breakpoint" : "breakpoint"); + if ( PP32_CPU_USER_BREAKIN_RCV(pp32) ) + strlength += sprintf(str + strlength, strlength ? " | breakin" : "breakin"); + f_stopped = 1; + } + #if 0 + else if ( PP32_CPU_CUR_PC(pp32) == PP32_CPU_CUR_PC(pp32) ) { + sprintf(str, "hang"); + f_stopped = 1; + } + #endif + else + sprintf(str, "running"); + cur_context = PP32_BRK_CUR_CONTEXT(pp32); + len += sprintf(page + off + len, "Context: %d, PC: 0x%04x, %s\n", cur_context, PP32_CPU_CUR_PC(pp32), str); + + if ( PP32_CPU_USER_BREAKPOINT_MET(pp32) ) { + strlength = 0; + if ( PP32_BRK_PC_MET(pp32, 0) ) + strlength += sprintf(str + strlength, "pc0"); + if ( PP32_BRK_PC_MET(pp32, 1) ) + strlength += sprintf(str + strlength, strlength ? " | pc1" : "pc1"); + if ( PP32_BRK_DATA_ADDR_MET(pp32, 0) ) + strlength += sprintf(str + strlength, strlength ? " | daddr0" : "daddr0"); + if ( PP32_BRK_DATA_ADDR_MET(pp32, 1) ) + strlength += sprintf(str + strlength, strlength ? " | daddr1" : "daddr1"); + if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 0) ) { + strlength += sprintf(str + strlength, strlength ? " | rdval0" : "rdval0"); + if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 0) ) { + if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) ) + strlength += sprintf(str + strlength, " =="); + else + strlength += sprintf(str + strlength, " <="); + } + else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 0) ) + strlength += sprintf(str + strlength, " >="); + } + if ( PP32_BRK_DATA_VALUE_RD_MET(pp32, 1) ) { + strlength += sprintf(str + strlength, strlength ? " | rdval1" : "rdval1"); + if ( PP32_BRK_DATA_VALUE_RD_LO_EQ(pp32, 1) ) { + if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) ) + strlength += sprintf(str + strlength, " =="); + else + strlength += sprintf(str + strlength, " <="); + } + else if ( PP32_BRK_DATA_VALUE_RD_GT_EQ(pp32, 1) ) + strlength += sprintf(str + strlength, " >="); + } + if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 0) ) { + strlength += sprintf(str + strlength, strlength ? " | wtval0" : "wtval0"); + if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 0) ) { + if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) ) + strlength += sprintf(str + strlength, " =="); + else + strlength += sprintf(str + strlength, " <="); + } + else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 0) ) + strlength += sprintf(str + strlength, " >="); + } + if ( PP32_BRK_DATA_VALUE_WR_MET(pp32, 1) ) { + strlength += sprintf(str + strlength, strlength ? " | wtval1" : "wtval1"); + if ( PP32_BRK_DATA_VALUE_WR_LO_EQ(pp32, 1) ) { + if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) ) + strlength += sprintf(str + strlength, " =="); + else + strlength += sprintf(str + strlength, " <="); + } + else if ( PP32_BRK_DATA_VALUE_WR_GT_EQ(pp32, 1) ) + strlength += sprintf(str + strlength, " >="); + } + len += sprintf(page + off + len, "break reason: %s\n", str); + } + + if ( f_stopped ) + { + len += sprintf(page + off + len, "General Purpose Register (Context %d):\n", cur_context); + for ( i = 0; i < 4; i++ ) { + for ( j = 0; j < 4; j++ ) + len += sprintf(page + off + len, " %2d: %08x", i + j * 4, *PP32_GP_CONTEXTi_REGn(pp32, cur_context, i + j * 4)); + len += sprintf(page + off + len, "\n"); + } + } + + len += sprintf(page + off + len, "break out on: break in - %s, stop - %s\n", + PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(pp32) ? stron : stroff, + PP32_CTRL_OPT_BREAKOUT_ON_STOP(pp32) ? stron : stroff); + len += sprintf(page + off + len, " stop on: break in - %s, break point - %s\n", + PP32_CTRL_OPT_STOP_ON_BREAKIN(pp32) ? stron : stroff, + PP32_CTRL_OPT_STOP_ON_BREAKPOINT(pp32) ? stron : stroff); + len += sprintf(page + off + len, "breakpoint:\n"); + len += sprintf(page + off + len, " pc0: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 0), PP32_BRK_GRPi_PCn(pp32, 0, 0) ? "group 0" : "off"); + len += sprintf(page + off + len, " pc1: 0x%08x, %s\n", *PP32_BRK_PC(pp32, 1), PP32_BRK_GRPi_PCn(pp32, 1, 1) ? "group 1" : "off"); + len += sprintf(page + off + len, " daddr0: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 0), PP32_BRK_GRPi_DATA_ADDRn(pp32, 0, 0) ? "group 0" : "off"); + len += sprintf(page + off + len, " daddr1: 0x%08x, %s\n", *PP32_BRK_DATA_ADDR(pp32, 1), PP32_BRK_GRPi_DATA_ADDRn(pp32, 1, 1) ? "group 1" : "off"); + len += sprintf(page + off + len, " rdval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 0)); + len += sprintf(page + off + len, " rdval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_RD(pp32, 1)); + len += sprintf(page + off + len, " wrval0: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 0)); + len += sprintf(page + off + len, " wrval1: 0x%08x\n", *PP32_BRK_DATA_VALUE_WR(pp32, 1)); + } + + *eof = 1; + + return len; +} + +static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data) +{ + char *str = NULL; + char *p; + unsigned int addr; + int str_buff_len = 1024; + + int len, rlen; + + int pp32 = 0; + + str = vmalloc(str_buff_len); + if (!str) { + return 0; + } + + len = count < str_buff_len ? count : str_buff_len - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ){ + vfree(str); + return 0; + } + + if ( strincmp(p, "pp32 ", 5) == 0 ) { + p += 5; + rlen -= 5; + + while ( rlen > 0 && *p >= '0' && *p <= '9' ) { + pp32 += *p - '0'; + p++; + rlen--; + } + while ( rlen > 0 && *p && *p <= ' ' ) { + p++; + rlen--; + } + + if ( pp32 >= NUM_OF_PP32 ) { + err("incorrect pp32 index - %d", pp32); + vfree(str); + return count; + } + } + + if ( stricmp(p, "start") == 0 ) + *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_RESTART; + else if ( stricmp(p, "stop") == 0 ) + *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STOP; + else if ( stricmp(p, "step") == 0 ) + *PP32_CTRL_CMD(pp32) = PP32_CTRL_CMD_STEP; + #ifdef CONFIG_VR9 + else if ( stricmp(p, "restart") == 0 ) + *PP32_FREEZE &= ~(1 << (pp32 << 4)); + else if ( stricmp(p, "freeze") == 0 ) + *PP32_FREEZE |= 1 << (pp32 << 4); + #endif + else if ( strincmp(p, "pc0 ", 4) == 0 ) { + p += 4; + rlen -= 4; + if ( stricmp(p, "off") == 0 ) { + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(0, 0); + *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN; + *PP32_BRK_PC(pp32, 0) = 0; + } + else { + addr = get_number(&p, &rlen, 1); + *PP32_BRK_PC(pp32, 0) = addr; + *PP32_BRK_PC_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(0, 0); + } + } + else if ( strincmp(p, "pc1 ", 4) == 0 ) { + p += 4; + rlen -= 4; + if ( stricmp(p, "off") == 0 ) { + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_OFF(1, 1); + *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN; + *PP32_BRK_PC(pp32, 1) = 0; + } + else { + addr = get_number(&p, &rlen, 1); + *PP32_BRK_PC(pp32, 1) = addr; + *PP32_BRK_PC_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_PCn_ON(1, 1); + } + } + else if ( strincmp(p, "daddr0 ", 7) == 0 ) { + p += 7; + rlen -= 7; + if ( stricmp(p, "off") == 0 ) { + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(0, 0); + *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN; + *PP32_BRK_DATA_ADDR(pp32, 0) = 0; + } + else { + addr = get_number(&p, &rlen, 1); + *PP32_BRK_DATA_ADDR(pp32, 0) = addr; + *PP32_BRK_DATA_ADDR_MASK(pp32, 0) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(0, 0); + } + } + else if ( strincmp(p, "daddr1 ", 7) == 0 ) { + p += 7; + rlen -= 7; + if ( stricmp(p, "off") == 0 ) { + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_OFF(1, 1); + *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN; + *PP32_BRK_DATA_ADDR(pp32, 1) = 0; + } + else { + addr = get_number(&p, &rlen, 1); + *PP32_BRK_DATA_ADDR(pp32, 1) = addr; + *PP32_BRK_DATA_ADDR_MASK(pp32, 1) = PP32_BRK_CONTEXT_MASK_EN | PP32_BRK_CONTEXT_MASK(0) | PP32_BRK_CONTEXT_MASK(1) | PP32_BRK_CONTEXT_MASK(2) | PP32_BRK_CONTEXT_MASK(3); + *PP32_BRK_TRIG(pp32) = PP32_BRK_GRPi_DATA_ADDRn_ON(1, 1); + } + } + else { + + printk("echo \"<command>\" > /proc/driver/ifx_ptm/pp32\n"); + printk(" command:\n"); + printk(" start - run pp32\n"); + printk(" stop - stop pp32\n"); + printk(" step - run pp32 with one step only\n"); + printk(" pc0 - pc0 <addr>/off, set break point PC0\n"); + printk(" pc1 - pc1 <addr>/off, set break point PC1\n"); + printk(" daddr0 - daddr0 <addr>/off, set break point data address 0\n"); + printk(" daddr0 - daddr1 <addr>/off, set break point data address 1\n"); + printk(" help - print this screen\n"); + } + + if ( *PP32_BRK_TRIG(pp32) ) + *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON; + else + *PP32_CTRL_OPT(pp32) = PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF; + vfree(str); + return count; +} + +#elif defined(CONFIG_DANUBE) + +static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + static const char *halt_stat[] = { + "reset", + "break in line", + "stop", + "step", + "code", + "data0", + "data1" + }; + static const char *brk_src_data[] = { + "off", + "read", + "write", + "read/write", + "write_equal", + "N/A", + "N/A", + "N/A" + }; + static const char *brk_src_code[] = { + "off", + "on" + }; + + int len = 0; + int i; + int k; + unsigned long bit; + int tsk; + + tsk = *PP32_DBG_TASK_NO & 0x03; + len += sprintf(page + off + len, "Task No %d, PC %04x\n", tsk, *PP32_DBG_CUR_PC & 0xFFFF); + + if ( !(*PP32_HALT_STAT & 0x01) ) + len += sprintf(page + off + len, " Halt State: Running\n"); + else { + len += sprintf(page + off + len, " Halt State: Stopped"); + k = 0; + for ( bit = 2, i = 0; bit <= (1 << 7); bit <<= 1, i++ ) + if ( (*PP32_HALT_STAT & bit) ) { + if ( !k ) { + len += sprintf(page + off + len, ", "); + k++; + } + else + len += sprintf(page + off + len, " | "); + len += sprintf(page + off + len, halt_stat[i]); + } + + len += sprintf(page + off + len, "\n"); + + len += sprintf(page + off + len, " Regs (Task %d):\n", tsk); + for ( i = 0; i < 8; i++ ) + len += sprintf(page + off + len, " %2d. %08x %2d. %08x\n", i, *PP32_DBG_REG_BASE(tsk, i), i + 8, *PP32_DBG_REG_BASE(tsk, i + 8)); + } + + len += sprintf(page + off + len, " Break Src: data1 - %s, data0 - %s, pc3 - %s, pc2 - %s, pc1 - %s, pc0 - %s\n", + brk_src_data[(*PP32_BRK_SRC >> 11) & 0x07], + brk_src_data[(*PP32_BRK_SRC >> 8) & 0x07], + brk_src_code[(*PP32_BRK_SRC >> 3) & 0x01], + brk_src_code[(*PP32_BRK_SRC >> 2) & 0x01], + brk_src_code[(*PP32_BRK_SRC >> 1) & 0x01], + brk_src_code[*PP32_BRK_SRC & 0x01]); + + for ( i = 0; i < 4; i++ ) + len += sprintf(page + off + len, " pc%d: %04x - %04x\n", i, *PP32_DBG_PC_MIN(i), *PP32_DBG_PC_MAX(i)); + + for ( i = 0; i < 2; i++ ) + len += sprintf(page + off + len, " data%d: %04x - %04x (%08x)\n", i, *PP32_DBG_DATA_MIN(i), *PP32_DBG_DATA_MAX(i), *PP32_DBG_DATA_VAL(i)); + + *eof = 1; + + return len; +} + +static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data) +{ + char *str; + char *p; + + int len, rlen; + int str_buff_len = 2048; + str = vmalloc(str_buff_len); + if (!str){ + return 0; + } + len = count < str_buff_len ? count : str_buff_len - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ) + vfree(str); + return 0; + + if ( stricmp(p, "start") == 0 ) + *PP32_DBG_CTRL = DBG_CTRL_START_SET(1); + else if ( stricmp(p, "stop") == 0 ) + *PP32_DBG_CTRL = DBG_CTRL_STOP_SET(1); + else if ( stricmp(p, "step") == 0 ) + *PP32_DBG_CTRL = DBG_CTRL_STEP_SET(1); + else if ( strincmp(p, "pc", 2) == 0 && p[2] >= '0' && p[2] <= '3' && p[3] <= ' ' ) { + int n = p[2] - '0'; + int on_off_flag = -1; + int addr_min, addr_max; + + p += 4; + rlen -= 4; + ignore_space(&p, &rlen); + + if ( strincmp(p, "off", 3) == 0 && p[3] <= ' ' ) { + p += 3; + rlen -= 3; + on_off_flag = 0; + } + else if ( strincmp(p, "on", 2) == 0 && p[2] <= ' ' ) { + p += 2; + rlen -= 2; + on_off_flag = 1; + } + ignore_space(&p, &rlen); + + if ( rlen ) { + addr_min = get_number(&p, &rlen, 1); + ignore_space(&p, &rlen); + if ( rlen ) + addr_max = get_number(&p, &rlen, 1); + else + addr_max = addr_min; + + *PP32_DBG_PC_MIN(n) = addr_min; + *PP32_DBG_PC_MAX(n) = addr_max; + } + + if ( on_off_flag == 0 ) + *PP32_BRK_SRC &= ~(1 << n); + else if ( on_off_flag > 0 ) + *PP32_BRK_SRC |= 1 << n; + } + else if ( strincmp(p, "data", 4) == 0 && p[4] >= '0' && p[4] <= '1' && p[5] <= ' ' ) { + const static char *data_cmd_str[] = {"r", "w", "rw", "w=", "off", "min", "min addr", "max", "max addr", "val", "value"}; + const static int data_cmd_len[] = {1, 1, 2, 2, 3, 3, 8, 3, 8, 3, 5}; + const static int data_cmd_idx[] = {1, 2, 3, 4, 0, 5, 5, 6, 6, 7, 7}; + int n = p[4] - '0'; + int on_off_flag = -1, on_off_mask = 0; + int addr_min = -1, addr_max = -1; + int value = 0, f_got_value = 0; + int stat = 0; + int i; + int tmp; + + p += 6; + rlen -= 6; + + while ( 1 ) { + ignore_space(&p, &rlen); + if ( rlen <= 0 ) + break; + for ( i = 0; i < NUM_ENTITY(data_cmd_str); i++ ) + if ( strincmp(p, data_cmd_str[i], data_cmd_len[i]) == 0 && p[data_cmd_len[i]] <= ' ' ) { + p += data_cmd_len[i]; + rlen -= data_cmd_len[i]; + stat = data_cmd_idx[i]; + if ( stat <= 4 ) { + on_off_mask = 7; + on_off_flag = stat; + } + break; + } + if ( i == NUM_ENTITY(data_cmd_str) ) { + if ( (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F') ) { + tmp = get_number(&p, &rlen, 1); + if ( stat <= 5 ) { + addr_min = tmp; + stat = 6; + } + else if ( stat >= 7 ) { + value = tmp; + f_got_value = 1; + } + else { + addr_max = tmp; + stat = 7; + } + } + else + for ( ; rlen && *p > ' '; rlen--, p++ ); + } + } + + if ( addr_min >= 0 ) + *PP32_DBG_DATA_MIN(n) = *PP32_DBG_DATA_MAX(n) = addr_min; + if ( addr_max >= 0 ) + *PP32_DBG_DATA_MAX(n) = addr_max; + if ( f_got_value ) + *PP32_DBG_DATA_VAL(n) = value; + if ( on_off_mask && on_off_flag >= 0 ) { + on_off_flag <<= n ? 11 : 8; + on_off_mask <<= n ? 11 : 8; + *PP32_BRK_SRC = (*PP32_BRK_SRC & ~on_off_mask) | on_off_flag; + } + } + else { + printk("echo \"<command>\" > /proc/eth/etop\n"); + printk(" command:\n"); + printk(" start - run pp32\n"); + printk(" stop - stop pp32\n"); + printk(" step - run pp32 with one step only\n"); + printk(" pc - pc? [on/off] [min addr] [max addr], set PC break point\n"); + printk(" data - data? [r/w/rw/w=/off] [min <addr>] [max <addr>] [val <value>], set data break point\n"); + printk(" help - print this screen\n"); + } + + vfree(str); + return count; +} + + #elif defined(CONFIG_AMAZON_SE) + +static int proc_read_pp32(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + static const char *halt_stat[] = { + "reset", + "break in line", + "stop", + "step", + "code", + "data0", + "data1" + }; + static const char *brk_src_data[] = { + "off", + "read", + "write", + "read/write", + "write_equal", + "N/A", + "N/A", + "N/A" + }; + static const char *brk_src_code[] = { + "off", + "on" + }; + + int len = 0; + int i; + int k; + unsigned long bit; + + len += sprintf(page + off + len, "Task No %d, PC %04x\n", *PP32_DBG_TASK_NO & 0x03, *PP32_DBG_CUR_PC & 0xFFFF); + + if ( !(*PP32_HALT_STAT & 0x01) ) + len += sprintf(page + off + len, " Halt State: Running\n"); + else + { + len += sprintf(page + off + len, " Halt State: Stopped"); + k = 0; + for ( bit = 2, i = 0; bit <= (1 << 7); bit <<= 1, i++ ) + if ( (*PP32_HALT_STAT & bit) ) + { + if ( !k ) + { + len += sprintf(page + off + len, ", "); + k++; + } + else + len += sprintf(page + off + len, " | "); + len += sprintf(page + off + len, halt_stat[i]); + } + + len += sprintf(page + off + len, "\n"); + } + + len += sprintf(page + off + len, " Break Src: data1 - %s, data0 - %s, pc3 - %s, pc2 - %s, pc1 - %s, pc0 - %s\n", + brk_src_data[(*PP32_BRK_SRC >> 11) & 0x07], brk_src_data[(*PP32_BRK_SRC >> 8) & 0x07], brk_src_code[(*PP32_BRK_SRC >> 3) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 2) & 0x01], brk_src_code[(*PP32_BRK_SRC >> 1) & 0x01], brk_src_code[*PP32_BRK_SRC & 0x01]); + +// for ( i = 0; i < 4; i++ ) +// len += sprintf(page + off + len, " pc%d: %04x - %04x\n", i, *PP32_DBG_PC_MIN(i), *PP32_DBG_PC_MAX(i)); + +// for ( i = 0; i < 2; i++ ) +// len += sprintf(page + off + len, " data%d: %04x - %04x (%08x)\n", i, *PP32_DBG_DATA_MIN(i), *PP32_DBG_DATA_MAX(i), *PP32_DBG_DATA_VAL(i)); + + *eof = 1; + + return len; +} + +static int proc_write_pp32(struct file *file, const char *buf, unsigned long count, void *data) +{ + char str[2048]; + char *p; + + int len, rlen; + + len = count < sizeof(str) ? count : sizeof(str) - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ) + return 0; + + if ( stricmp(str, "start") == 0 ) + *PP32_DBG_CTRL = DBG_CTRL_RESTART; + else if ( stricmp(str, "stop") == 0 ) + *PP32_DBG_CTRL = DBG_CTRL_STOP; +// else if ( stricmp(str, "step") == 0 ) +// *PP32_DBG_CTRL = DBG_CTRL_STEP_SET(1); + else + { + printk("echo \"<command>\" > /proc/eth/etop\n"); + printk(" command:\n"); + printk(" start - run pp32\n"); + printk(" stop - stop pp32\n"); +// printk(" step - run pp32 with one step only\n"); + printk(" help - print this screen\n"); + } + + return count; +} + + #endif + +#endif + +#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC + +static INLINE int print_htu(char *buf, int i) +{ + int len = 0; + + if ( HTU_ENTRY(i)->vld ) { + len += sprintf(buf + len, "%2d. valid\n", i); + len += sprintf(buf + len, " entry 0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(unsigned int*)HTU_ENTRY(i), HTU_ENTRY(i)->pid, HTU_ENTRY(i)->vpi, HTU_ENTRY(i)->vci, HTU_ENTRY(i)->pti); + len += sprintf(buf + len, " mask 0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(unsigned int*)HTU_MASK(i), HTU_MASK(i)->pid_mask, HTU_MASK(i)->vpi_mask, HTU_MASK(i)->vci_mask, HTU_MASK(i)->pti_mask); + len += sprintf(buf + len, " result 0x%08x - type: %s, qid: %d", *(unsigned int*)HTU_RESULT(i), HTU_RESULT(i)->type ? "cell" : "AAL5", HTU_RESULT(i)->qid); + if ( HTU_RESULT(i)->type ) + len += sprintf(buf + len, ", cell id: %d, verification: %s", HTU_RESULT(i)->cellid, HTU_RESULT(i)->ven ? "on" : "off"); + len += sprintf(buf + len, "\n"); + } + else + len += sprintf(buf + len, "%2d. invalid\n", i); + + return len; +} + +static int proc_read_htu(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + int len_max = off + count; + char *pstr; + int llen; + char *str; + int htuts = *CFG_WRX_HTUTS; + int i; + + str = vmalloc (1024); + if (!str) + return 0; + + pstr = *start = page; + + llen = sprintf(pstr, "HTU Table (Max %d):\n", htuts); + pstr += llen; + len += llen; + + for ( i = 0; i < htuts; i++ ) { + llen = print_htu(str, i); + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_HTU_OVERRUN_END; + } + + *eof = 1; + vfree(str); + return len - off; + +PROC_READ_HTU_OVERRUN_END: + + return len - llen - off; +} + +static INLINE int print_tx_queue(char *buf, int i) +{ + int len = 0; + + if ( (*WTX_DMACH_ON & (1 << i)) ) { + len += sprintf(buf + len, "%2d. valid\n", i); + len += sprintf(buf + len, " queue 0x%08x - sbid %u, qsb vcid %u, qsb %s\n", (unsigned int)WTX_QUEUE_CONFIG(i), (unsigned int)WTX_QUEUE_CONFIG(i)->sbid, (unsigned int)WTX_QUEUE_CONFIG(i)->qsb_vcid, WTX_QUEUE_CONFIG(i)->qsben ? "enable" : "disable"); + len += sprintf(buf + len, " dma 0x%08x - base %08x, len %u, vlddes %u\n", (unsigned int)WTX_DMA_CHANNEL_CONFIG(i), WTX_DMA_CHANNEL_CONFIG(i)->desba, WTX_DMA_CHANNEL_CONFIG(i)->deslen, WTX_DMA_CHANNEL_CONFIG(i)->vlddes); + } + else + len += sprintf(buf + len, "%2d. invalid\n", i); + + return len; +} + +static int proc_read_txq(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + int len_max = off + count; + char *pstr; + int llen; + int str_buff_len = 1024; + char *str; + + int i; + + str = vmalloc(str_buff_len); + if (!str){ + return 0; + } + pstr = *start = page; + + llen = sprintf(pstr, "TX Queue Config (Max %d):\n", *CFG_WTX_DCHNUM); + pstr += llen; + len += llen; + + for ( i = 0; i < 16; i++ ) { + llen = print_tx_queue(str, i); + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_HTU_OVERRUN_END; + } + + + *eof = 1; + + vfree(str); + return len - off; + +PROC_READ_HTU_OVERRUN_END: + + return len - llen - off; +} + + #if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + +static int proc_read_retx_fw(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + unsigned int next_dtu_sid_out, last_dtu_sid_in, next_cell_sid_out, isr_cell_id; + unsigned int curr_time, sec_counter, curr_efb; + struct Retx_adsl_ppe_intf adsl_ppe_intf; + + adsl_ppe_intf = *RETX_ADSL_PPE_INTF; + next_dtu_sid_out = *NEXT_DTU_SID_OUT; + last_dtu_sid_in = *LAST_DTU_SID_IN; + next_cell_sid_out = *NEXT_CELL_SID_OUT; + isr_cell_id = *ISR_CELL_ID; + + curr_time = *URetx_curr_time; + sec_counter = *URetx_sec_counter; + curr_efb = *RxCURR_EFB; + + + len += sprintf(page + off + len, "Adsl-PPE Interface:\n"); + len += sprintf(page + off + len, " dtu_sid = 0x%02x [%3u]\n", adsl_ppe_intf.dtu_sid, adsl_ppe_intf.dtu_sid); + len += sprintf(page + off + len, " dtu_timestamp = 0x%02x\n", adsl_ppe_intf.dtu_timestamp); + len += sprintf(page + off + len, " local_time = 0x%02x\n", adsl_ppe_intf.local_time); + len += sprintf(page + off + len, " is_last_cw = %u\n", adsl_ppe_intf.is_last_cw); + len += sprintf(page + off + len, " reinit_flag = %u\n", adsl_ppe_intf.reinit_flag); + len += sprintf(page + off + len, " is_bad_cw = %u\n", adsl_ppe_intf.is_bad_cw); + len += sprintf(page + off + len, "\n"); + + + len += sprintf(page + off + len, "Retx Firmware Context:\n"); + len += sprintf(page + off + len, " next_dtu_sid_out (0x%08x) = 0x%02x [%3u]\n", (unsigned int )NEXT_DTU_SID_OUT, next_dtu_sid_out, next_dtu_sid_out); + len += sprintf(page + off + len, " last_dtu_sid_in (0x%08x) = 0x%02x [%3u]\n", (unsigned int )LAST_DTU_SID_IN, last_dtu_sid_in, last_dtu_sid_in); + len += sprintf(page + off + len, " next_cell_sid_out (0x%08x) = %u\n", (unsigned int )NEXT_CELL_SID_OUT, next_cell_sid_out); + len += sprintf(page + off + len, " isr_cell_id (0x%08x) = %u\n", (unsigned int )ISR_CELL_ID, isr_cell_id); + len += sprintf(page + off + len, " pb_cell_search_idx (0x%08x) = %u\n", (unsigned int )PB_CELL_SEARCH_IDX, *PB_CELL_SEARCH_IDX); + len += sprintf(page + off + len, " pb_read_pend_flag (0x%08x) = %u\n", (unsigned int )PB_READ_PEND_FLAG, *PB_READ_PEND_FLAG); + len += sprintf(page + off + len, " rfbi_first_cw (0x%08x) = %u\n", (unsigned int )RFBI_FIRST_CW, *RFBI_FIRST_CW); + len += sprintf(page + off + len, " rfbi_bad_cw (0x%08x) = %u\n", (unsigned int )RFBI_BAD_CW, *RFBI_BAD_CW); + len += sprintf(page + off + len, " rfbi_invalid_cw (0x%08x) = %u\n", (unsigned int )RFBI_INVALID_CW, *RFBI_INVALID_CW); + len += sprintf(page + off + len, " rfbi_retx_cw (0x%08x) = %u\n", (unsigned int )RFBI_RETX_CW, *RFBI_RETX_CW); + len += sprintf(page + off + len, " rfbi_chk_dtu_status (0x%08x) = %u\n", (unsigned int )RFBI_CHK_DTU_STATUS,*RFBI_CHK_DTU_STATUS); + len += sprintf(page + off + len, "\n"); + + + len += sprintf(page + off + len, "SFSM Status: bc0 bc1 \n\n"); + len += sprintf(page + off + len, " state = %-22s , %s\n", + (*__WRXCTXT_PortState(0) & 3) == 0 ? "Hunt" : + (*__WRXCTXT_PortState(0) & 3) == 1 ? "Pre_sync" : + (*__WRXCTXT_PortState(0) & 3) == 2 ? "Sync" : + "Unknown(error)", + (*__WRXCTXT_PortState(1) & 3) == 0 ? "Hunt" : + (*__WRXCTXT_PortState(1) & 3) == 1 ? "Pre_sync" : + (*__WRXCTXT_PortState(1) & 3) == 2 ? "Sync" : + "Unknown(error)" ); + len += sprintf(page + off + len, " dbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n", + SFSM_DBA(0)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_DBA(0)->dbase + 0x2000), + SFSM_DBA(1)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_DBA(1)->dbase + 0x2000)); + len += sprintf(page + off + len, " cbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n", + SFSM_CBA(0)->cbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_CBA(0)->cbase + 0x2000), + SFSM_CBA(1)->cbase, (unsigned int)PPM_INT_UNIT_ADDR(SFSM_CBA(1)->cbase + 0x2000)); + len += sprintf(page + off + len, " sen = %-22d , %d\n", SFSM_CFG(0)->sen, SFSM_CFG(1)->sen ); + len += sprintf(page + off + len, " idlekeep = %-22d , %d\n", SFSM_CFG(0)->idlekeep, SFSM_CFG(1)->idlekeep ); + len += sprintf(page + off + len, " pnum = %-22d , %d\n", SFSM_CFG(0)->pnum, SFSM_CFG(1)->pnum ); + len += sprintf(page + off + len, " pptr = %-22d , %d\n", SFSM_PGCNT(0)->pptr, SFSM_PGCNT(1)->pptr); + len += sprintf(page + off + len, " upage = %-22d , %d\n", SFSM_PGCNT(0)->upage, SFSM_PGCNT(1)->upage); + len += sprintf(page + off + len, " l2_rdptr = %-22d , %d\n", *__WRXCTXT_L2_RdPtr(0), *__WRXCTXT_L2_RdPtr(1) ); + len += sprintf(page + off + len, " l2_page = %-22d , %d\n", *__WRXCTXT_L2Pages(0), *__WRXCTXT_L2Pages(1) ); + len += sprintf(page + off + len, "\n"); + + + len += sprintf(page + off + len, "FFSM Status: bc0 bc1 \n\n"); + len += sprintf(page + off + len, " dbase = 0x%04x ( 0x%08x ) , 0x%04x ( 0x%08x )\n", + FFSM_DBA(0)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(FFSM_DBA(0)->dbase + 0x2000), + FFSM_DBA(1)->dbase, (unsigned int)PPM_INT_UNIT_ADDR(FFSM_DBA(1)->dbase + 0x2000)); + len += sprintf(page + off + len, " pnum = %-22d , %d\n", FFSM_CFG(0)->pnum, FFSM_CFG(1)->pnum); + len += sprintf(page + off + len, " vpage = %-22d , %d\n", FFSM_PGCNT(0)->vpage, FFSM_PGCNT(1)->vpage); + len += sprintf(page + off + len, " ival = %-22d , %d\n", FFSM_PGCNT(0)->ival, FFSM_PGCNT(1)->ival); + len += sprintf(page + off + len, " tc_wrptr = %-22d , %d\n", *__WTXCTXT_TC_WRPTR(0), *__WTXCTXT_TC_WRPTR(1)); + len += sprintf(page + off + len, "\n"); + + + len += sprintf(page + off + len, "Misc: \n\n"); + len += sprintf(page + off + len, " curr_time = %08x\n", curr_time ); + len += sprintf(page + off + len, " sec_counter = %d\n", sec_counter ); + len += sprintf(page + off + len, " curr_efb = %d\n", curr_efb ); + len += sprintf(page + off + len, "\n"); + + *eof = 1; + + return len; +} + +static inline int is_valid(unsigned int * dtu_vld_stat, int dtu_sid) +{ + int dw_idx = (dtu_sid / 32) & 7; + int bit_pos = dtu_sid % 32; + + return dtu_vld_stat[dw_idx] & (0x80000000 >> bit_pos); +} + +static int proc_read_retx_stats(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int i; + int len = 0; + int len_max = off + count; + char *pstr; + char str[2048]; + int llen = 0; + + unsigned int next_dtu_sid_out, last_dtu_sid_in, next_cell_sid_out; + unsigned int dtu_vld_stat[8]; + struct DTU_stat_info dtu_stat_info[256]; + struct Retx_adsl_ppe_intf adsl_ppe_intf; + + pstr = *start = page; + + __sync(); + + // capture a snapshot of internal status + next_dtu_sid_out = *NEXT_DTU_SID_OUT; + last_dtu_sid_in = *LAST_DTU_SID_IN; + next_cell_sid_out = *NEXT_CELL_SID_OUT; + adsl_ppe_intf = *RETX_ADSL_PPE_INTF; + + memcpy(&dtu_vld_stat, (void *)DTU_VLD_STAT, sizeof(dtu_vld_stat)); + memcpy(&dtu_stat_info, (void *)DTU_STAT_INFO, sizeof(dtu_stat_info)); + + + llen += sprintf(str + llen, "Adsl-PPE Interface:\n"); + llen += sprintf(str + llen, " dtu_sid = 0x%02x [%3u]\n", adsl_ppe_intf.dtu_sid, adsl_ppe_intf.dtu_sid); + llen += sprintf(str + llen, " dtu_timestamp = 0x%02x\n", adsl_ppe_intf.dtu_timestamp); + llen += sprintf(str + llen, " local_time = 0x%02x\n", adsl_ppe_intf.local_time); + llen += sprintf(str + llen, " is_last_cw = %u\n", adsl_ppe_intf.is_last_cw); + llen += sprintf(str + llen, " reinit_flag = %u\n", adsl_ppe_intf.reinit_flag); + llen += sprintf(str + llen, " is_bad_cw = %u\n", adsl_ppe_intf.is_bad_cw); + llen += sprintf(str + llen, "\n"); + + llen += sprintf(str + llen, "Retx Internal State:\n"); + llen += sprintf(str + llen, " next_dtu_sid_out (0x%08x) = 0x%02x [%3u]\n", (unsigned int )NEXT_DTU_SID_OUT, next_dtu_sid_out, next_dtu_sid_out); + llen += sprintf(str + llen, " last_dtu_sid_in (0x%08x) = 0x%02x [%3u]\n", (unsigned int )LAST_DTU_SID_IN, last_dtu_sid_in, last_dtu_sid_in); + llen += sprintf(str + llen, " next_cell_sid_out (0x%08x) = %u\n", (unsigned int )NEXT_CELL_SID_OUT, next_cell_sid_out); + llen += sprintf(str + llen, " dtu_valid_stat (0x%08x)\n", (unsigned int )DTU_VLD_STAT); + llen += sprintf(str + llen, " dtu_stat_info (0x%08x)\n", (unsigned int )DTU_STAT_INFO); + llen += sprintf(str + llen, " pb_buffer_usage (0x%08x)\n", (unsigned int )PB_BUFFER_USAGE); + + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_RETX_STATS_OVERRUN_END; + llen = 0; + + + llen += sprintf(str + llen, "\n"); + llen += sprintf(str + llen, "DTU_VALID_STAT: [0x%08x]:\n", (unsigned int)DTU_VLD_STAT); + llen += sprintf(str + llen, "%08X: %08X %08X %08X %08X %08X %08X %08X %08X\n", + (unsigned int)DTU_VLD_STAT, + dtu_vld_stat[0], dtu_vld_stat[1], dtu_vld_stat[2], dtu_vld_stat[3], + dtu_vld_stat[4], dtu_vld_stat[5], dtu_vld_stat[6], dtu_vld_stat[7]); + + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_RETX_STATS_OVERRUN_END; + llen = 0; + + + llen += sprintf(str + llen, "\n"); + llen += sprintf(str + llen, "DTU_STAT_INFO: [0x%08x]:\n", (unsigned int)DTU_STAT_INFO); + llen += sprintf(str + llen, "dtu_id ts complete bad cell_cnt dtu_rd_ptr dtu_wr_ptr\n"); + llen += sprintf(str + llen, "---------------------------------------------------------------------\n"); + for ( i = 0; i < 256; i++ ) { + if ( !is_valid(dtu_vld_stat, i) ) + continue; + + llen += sprintf(str + llen, "0x%02x [%3u] 0x%02x %d %d %3d %5d %5d\n", + i, i, + DTU_STAT_INFO[i].time_stamp, + DTU_STAT_INFO[i].complete, + DTU_STAT_INFO[i].bad, + DTU_STAT_INFO[i].cell_cnt, + DTU_STAT_INFO[i].dtu_rd_ptr, + DTU_STAT_INFO[i].dtu_wr_ptr ); + + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) + { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_RETX_STATS_OVERRUN_END; + llen = 0; + } + + + llen += sprintf(str + llen, "\n"); + llen += sprintf(str + llen, "Playout buffer status --- valid status [0x%08x]:\n", (unsigned int)PB_BUFFER_USAGE); + for( i = 0; i < RETX_MODE_CFG->buff_size; i += 8 ) { + llen += sprintf(str + llen, "%08X: %08X %08X %08X %08X %08X %08X %08X %08X\n", + (unsigned int)PB_BUFFER_USAGE + i * sizeof(unsigned int), + PB_BUFFER_USAGE[i], PB_BUFFER_USAGE[i+1], PB_BUFFER_USAGE[i+2], PB_BUFFER_USAGE[i+3], + PB_BUFFER_USAGE[i+4], PB_BUFFER_USAGE[i+5], PB_BUFFER_USAGE[i+6], PB_BUFFER_USAGE[i+7]); + } + + if ( len <= off && len + llen > off ) { + memcpy(pstr, str + off - len, len + llen - off); + pstr += len + llen - off; + } + else if ( len > off ) { + memcpy(pstr, str, llen); + pstr += llen; + } + len += llen; + if ( len >= len_max ) + goto PROC_READ_RETX_STATS_OVERRUN_END; + llen = 0; + + + *eof = 1; + + return len - off; + +PROC_READ_RETX_STATS_OVERRUN_END: + return len - llen - off; +} + +static int proc_write_retx_stats(struct file *file, const char *buf, unsigned long count, void *data) +{ + char str[2048]; + char *p; + + int len, rlen; + + len = count < sizeof(str) ? count : sizeof(str) - 1; + rlen = len - copy_from_user(str, buf, len); + while ( rlen && str[rlen - 1] <= ' ' ) + rlen--; + str[rlen] = 0; + for ( p = str; *p && *p <= ' '; p++, rlen-- ); + if ( !*p ) + return 0; + + if ( stricmp(p, "help") == 0 ) { + printk("echo clear_pb > /proc/driver/ifx_atm/retx_stats \n"); + printk(" :clear context in playout buffer\n\n"); + printk("echo read_pb <pb_index> <cell_num> > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : read playout buffer contents\n\n"); + printk("echo read_[r|t]x_cb > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : read cell buffer\n\n"); + printk("echo clear_[r|t]x_cb > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : clear cell buffer\n\n"); + printk("echo read_bad_dtu_intf_rec > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : read bad dtu intrface information record\n\n"); + printk("echo clear_bad_dtu_intf_rec > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : clear bad dtu interface information record\n\n"); + printk("echo read_wrx_context [i] > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : clear bad dtu interface information record\n\n"); + printk("echo read_intf_rec > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : read interface info record buffer\n\n"); + printk("echo reinit_intf_rec > /proc/driver/ifx_atm/retx_stats\n"); + printk(" : reinit intf record, must be called before showtime\n\n"); + } + else if ( stricmp(p, "reinit_intf_rec") == 0 ) { + int i = 0; + struct Retx_adsl_ppe_intf_rec rec[16]; + + *DBG_DTU_INTF_WRPTR = 0; + *DBG_INTF_FCW_DUP_CNT = 0; + *DBG_INTF_SID_CHANGE_IN_DTU_CNT = 0; + *DBG_INTF_LCW_DUP_CNT = 0; + + *DBG_RFBI_DONE_INT_CNT = 0; + *DBG_RFBI_INTV0 = 0; + *DBG_RFBI_INTV1 = 0; + *DBG_RFBI_BC0_INVALID_CNT = 0; + *DBG_RFBI_LAST_T = 0; + *DBG_DREG_BEG_END = 0; + + memset((void *) DBG_INTF_INFO(0), 0, sizeof(rec)); + for( i = 0; i < 16; i++ ) + DBG_INTF_INFO(i)->res1_1 = 1; + DBG_INTF_INFO(15)->dtu_sid = 255; + } + else if ( stricmp(p, "read_intf_rec") == 0 ) { + int i, cnt; + unsigned int dtu_intf_wrptr, fcw_dup_cnt, sid_change_in_dtu_cnt, lcw_dup_cnt ; + unsigned int rfbi_done_int_cnt, rfbi_intv0, rfbi_intv1, rfbi_bc0_invalid_cnt, dreg_beg_end; + struct Retx_adsl_ppe_intf_rec rec[16]; + + memcpy((void *) rec, (void *) DBG_INTF_INFO(0), sizeof(rec)); + + dtu_intf_wrptr = *DBG_DTU_INTF_WRPTR; + fcw_dup_cnt = *DBG_INTF_FCW_DUP_CNT; + sid_change_in_dtu_cnt = *DBG_INTF_SID_CHANGE_IN_DTU_CNT; + lcw_dup_cnt = *DBG_INTF_LCW_DUP_CNT; + + rfbi_done_int_cnt = *DBG_RFBI_DONE_INT_CNT; + rfbi_intv0 = *DBG_RFBI_INTV0; + rfbi_intv1 = *DBG_RFBI_INTV1; + rfbi_bc0_invalid_cnt = *DBG_RFBI_BC0_INVALID_CNT; + dreg_beg_end = *DBG_DREG_BEG_END; + + printk("PPE-Adsl Interface recrod [addr 0x23F0]:\n\n"); + + printk(" rfbi_done_int_cnt = %d [0x%x] \n", rfbi_done_int_cnt, rfbi_done_int_cnt); + printk(" rfbi_intv = 0x%08x 0x%08x [%d, %d, %d, %d, %d, %d, %d, %d]\n", + rfbi_intv0, rfbi_intv1, + rfbi_intv0 >> 24, (rfbi_intv0>>16) & 0xff, (rfbi_intv0>>8) & 0xff, rfbi_intv0 & 0xff, + rfbi_intv1 >> 24, (rfbi_intv1>>16) & 0xff, (rfbi_intv1>>8) & 0xff, rfbi_intv1 & 0xff + ); + printk(" rfbi_bc0_invld_cnt = %d\n", rfbi_bc0_invalid_cnt); + printk(" dreg_beg_end = %d, %d\n\n", dreg_beg_end >> 16, dreg_beg_end & 0xffff); + + printk(" wrptr = %d [0x%x] \n", dtu_intf_wrptr, dtu_intf_wrptr); + printk(" fcw_dup_cnt = %d\n", fcw_dup_cnt); + printk(" sid_chg_cnt = %d\n", sid_change_in_dtu_cnt); + printk(" lcw_dup_cnt = %d\n\n", lcw_dup_cnt); + + + printk(" idx itf_dw0 itf_dw1 dtu_sid timestamp local_time res1 last_cw bad_flag reinit\n"); + printk(" -------------------------------------------------------------------------------------\n"); + for ( i = (dtu_intf_wrptr + 1) % 16, cnt = 0; cnt < 16; cnt ++, i = (i + 1) % 16 ) { + if(cnt < 15) + printk(" "); + else + printk(" *"); + printk("%3d %04x %04x %3d[%02x] %3d[%02x] %3d[%02x] 0x%02x %d %d %d\n", + i, + (*(unsigned int *)&rec[i]) & 0xffff, + (*(unsigned int *)&rec[i]) >> 16, + rec[i].dtu_sid, rec[i].dtu_sid, + rec[i].dtu_timestamp, rec[i].dtu_timestamp, + rec[i].local_time, rec[i].local_time, + rec[i].res1_1, + rec[i].is_last_cw, + rec[i].is_bad_cw, + rec[i].reinit_flag ); + } + } + else if ( stricmp(p, "read_wrx_context") == 0 ) { + int i = 0; + int flag = 0; + for( i = 0; i < 8; ++i ) { + if ( !WRX_QUEUE_CONTEXT(i)->curr_des0 || !WRX_QUEUE_CONTEXT(i)->curr_des1 ) + continue; + + flag = 1; + printk("WRX queue context [ %d ]: \n", i); + printk(" curr_len = %4d, mfs = %d, ec = %d, clp1 = %d, aal5dp = %d\n", + WRX_QUEUE_CONTEXT(i)->curr_len, WRX_QUEUE_CONTEXT(i)->mfs, + WRX_QUEUE_CONTEXT(i)->ec, WRX_QUEUE_CONTEXT(i)->clp1, + WRX_QUEUE_CONTEXT(i)->aal5dp); + printk(" initcrc = %08x\n", WRX_QUEUE_CONTEXT(i)->intcrc); + printk(" currdes = %08x %08x\n", + WRX_QUEUE_CONTEXT(i)->curr_des0, WRX_QUEUE_CONTEXT(i)->curr_des1); + printk(" last_dw = %08x\n\n", WRX_QUEUE_CONTEXT(i)->last_dword); + if( WRX_QUEUE_CONTEXT(i)->curr_len ) { + int j = 0; + unsigned char *p_char; + struct rx_descriptor *desc = (struct rx_descriptor *)&(WRX_QUEUE_CONTEXT(i)->curr_des0); + p_char = (unsigned char *)(((unsigned int)desc->dataptr << 2) | KSEG1); + printk(" Data in SDRAM:\n "); + + for ( j = 0 ; j < WRX_QUEUE_CONTEXT(i)->curr_len; ++j ) { + printk ("%02x", p_char[j]); + if ( j % 16 == 15 ) + printk("\n "); + else if ( j % 4 == 3 ) + printk (" "); + } + printk("\n\n"); + } + } + if ( !flag ) { + printk("No active wrx queue context\n"); + } + } + else if ( stricmp(p, "clear_pb") == 0 ) { + if ( g_retx_playout_buffer ) + memset((void *)g_retx_playout_buffer, 0, RETX_PLAYOUT_BUFFER_SIZE); + } + else if ( stricmp(p, "read_bad_dtu_intf_rec") == 0 ) { + struct Retx_adsl_ppe_intf first_dtu_intf, last_dtu_intf; + first_dtu_intf = *FIRST_BAD_REC_RETX_ADSL_PPE_INTF; + last_dtu_intf = *BAD_REC_RETX_ADSL_PPE_INTF; + + printk("\nAdsl-PPE Interface for first and last DTU of recent noise:\n\n"); + printk(" dtu_sid = 0x%02x [%3u], 0x%02x [%3u]\n", + first_dtu_intf.dtu_sid, first_dtu_intf.dtu_sid, + last_dtu_intf.dtu_sid, last_dtu_intf.dtu_sid); + printk(" dtu_timestamp = 0x%02x , 0x%02x\n", + first_dtu_intf.dtu_timestamp, last_dtu_intf.dtu_timestamp); + printk(" local_time = 0x%02x , 0x%02x\n", + first_dtu_intf.local_time, last_dtu_intf.local_time); + printk(" is_last_cw = %u , %u\n", + first_dtu_intf.is_last_cw, last_dtu_intf.is_last_cw); + printk(" reinit_flag = %u , %u\n", + first_dtu_intf.reinit_flag, last_dtu_intf.reinit_flag); + printk(" is_bad_cw = %u , %u\n\n", + first_dtu_intf.is_bad_cw, last_dtu_intf.is_bad_cw); + } + else if ( stricmp(p, "clear_bad_dtu_intf_rec") == 0 ) { + memset((void *)BAD_REC_RETX_ADSL_PPE_INTF, 0, sizeof(struct Retx_adsl_ppe_intf)); + memset((void *)FIRST_BAD_REC_RETX_ADSL_PPE_INTF, 0, sizeof(struct Retx_adsl_ppe_intf)); + } + else if ( stricmp(p, "clear_tx_cb") == 0 ) { + unsigned int *dbase0; + unsigned int pnum0; + + dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( FFSM_DBA(0)->dbase + 0x2000); + pnum0 = FFSM_CFG(0)->pnum; + memset(dbase0, 0, 14 * sizeof(unsigned int ) * pnum0); + } + else if ( stricmp(p, "clear_rx_cb") == 0 ) { + unsigned int *dbase0, *cbase0, *dbase1, *cbase1; + unsigned int pnum0; + + dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(0)->dbase + 0x2000); + cbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(0)->cbase + 0x2000); + + dbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(1)->dbase + 0x2000); + cbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(1)->cbase + 0x2000); + + pnum0 = SFSM_CFG(0)->pnum; + + memset(dbase0, 0, 14 * sizeof(unsigned int ) * pnum0); + memset(cbase0, 0, sizeof(unsigned int ) * pnum0); + + memset(dbase1, 0, 14 * sizeof(unsigned int )); + memset(cbase1, 0, sizeof(unsigned int )); + } + else if ( strnicmp(p, "read_tx_cb", 10) == 0 ) { + unsigned int *dbase0; + unsigned int pnum0, i; + unsigned int * cell; + + dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( FFSM_DBA(0)->dbase + 0x2000); + pnum0 = FFSM_CFG(0)->pnum; + + printk("ATM TX BC 0 CELL data/ctrl buffer:\n\n"); + for(i = 0; i < pnum0 ; ++ i) { + cell = dbase0 + i * 14; + printk("cell %2d: %08x %08x\n", i, cell[0], cell[1]); + printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]); + printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]); + printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]); + } + } + else if ( strnicmp(p, "read_rx_cb", 10) == 0 ) { + unsigned int *dbase0, *cbase0, *dbase1, *cbase1; + unsigned int pnum0, i; + unsigned int * cell; + + dbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(0)->dbase + 0x2000); + cbase0 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(0)->cbase + 0x2000); + + dbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_DBA(1)->dbase + 0x2000); + cbase1 = (unsigned int *)PPM_INT_UNIT_ADDR( SFSM_CBA(1)->cbase + 0x2000); + + pnum0 = SFSM_CFG(0)->pnum; + + printk("ATM RX BC 0 CELL data/ctrl buffer:\n\n"); + for(i = 0; i < pnum0 ; ++ i) { + struct Retx_ctrl_field * p_ctrl; + + cell = dbase0 + i * 14; + p_ctrl = (struct Retx_ctrl_field *) ( &cbase0[i]); + printk("cell %2d: %08x %08x -- [%08x]:", i, cell[0], cell[1], cbase0[i]); + + printk("l2_drop: %d, retx: %d", p_ctrl->l2_drop, p_ctrl->retx); + if ( p_ctrl->retx ) { + printk(", dtu_sid = %u, cell_sid = %u", p_ctrl->dtu_sid, p_ctrl->cell_sid); + } + + printk("\n"); + + printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]); + printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]); + printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]); + } + + printk("\n"); + printk("ATM RX BC 1 CELL data/ctrl buffer:\n\n"); + cell = dbase1; + printk("cell %2d: %08x %08x -- [%08x]: dtu_sid:%3d, cell_sid:%3d, next_ptr: %4d\n", + 0, cell[0], cell[1], cbase0[i], ( cell[1] >> 16) & 0xff, (cell[1] >> 24) & 0xff, cell[1] & 0xffff ); + printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]); + printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]); + printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]); + } + else if ( strnicmp(p, "read_pb ", 8) == 0 ) + { + int start_cell_idx = 0; + int cell_num = 0; + unsigned int *cell; + unsigned int pb_buff_size = RETX_MODE_CFG->buff_size * 32; + + p += 8; + rlen -= 8; + ignore_space(&p, &rlen); + + start_cell_idx = get_number(&p, &rlen, 0); + ignore_space(&p, &rlen); + cell_num = get_number(&p, &rlen, 0); + + if ( start_cell_idx >= pb_buff_size ) { + printk(" Invalid cell index\n"); + } + else { + int i; + if ( cell_num < 0 ) + cell_num = 1; + + if ( cell_num + start_cell_idx > pb_buff_size ) + cell_num = pb_buff_size - start_cell_idx; + + for ( i = 0; i < cell_num ; ++i ) { + cell = (unsigned int *)((unsigned int *)g_retx_playout_buffer + (14 * (start_cell_idx + i))); + printk("cell %4d: %08x %08x [next_ptr = %4u, dtu_sid = %3u, cell_sid = %3u]\n", + start_cell_idx + i, cell[0], cell[1], cell[1] & 0xffff, (cell[1] >> 16) & 0xff, (cell[1] >> 24) & 0xff); + printk(" %08x %08x %08x %08x\n", cell[2], cell[3], cell[4], cell[5]); + printk(" %08x %08x %08x %08x\n", cell[6], cell[7], cell[8], cell[9]); + printk(" %08x %08x %08x %08x\n", cell[10], cell[11], cell[12], cell[13]); + } + } + } + + return count; +} + +static int proc_read_retx_cfg(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page + off + len, "ReTX FW Config:\n"); + len += sprintf(page + off + len, " RETX_MODE_CFG = 0x%08x, invld_range=%u, buff_size=%u, retx=%u\n", *(volatile unsigned int *)RETX_MODE_CFG, (unsigned int)RETX_MODE_CFG->invld_range, (unsigned int)RETX_MODE_CFG->buff_size * 32, (unsigned int)RETX_MODE_CFG->retx_en); + len += sprintf(page + off + len, " RETX_TSYNC_CFG = 0x%08x, fw_alpha=%u, sync_inp=%u\n", *(volatile unsigned int *)RETX_TSYNC_CFG, (unsigned int)RETX_TSYNC_CFG->fw_alpha, (unsigned int)RETX_TSYNC_CFG->sync_inp); + len += sprintf(page + off + len, " RETX_TD_CFG = 0x%08x, td_max=%u, td_min=%u\n", *(volatile unsigned int *)RETX_TD_CFG, (unsigned int)RETX_TD_CFG->td_max, (unsigned int)RETX_TD_CFG->td_min); + len += sprintf(page + off + len, " RETX_PLAYOUT_BUFFER_BASE = 0x%08x\n", *RETX_PLAYOUT_BUFFER_BASE); + len += sprintf(page + off + len, " RETX_SERVICE_HEADER_CFG = 0x%08x\n", *RETX_SERVICE_HEADER_CFG); + len += sprintf(page + off + len, " RETX_MASK_HEADER_CFG = 0x%08x\n", *RETX_MASK_HEADER_CFG); + len += sprintf(page + off + len, " RETX_MIB_TIMER_CFG = 0x%08x, tick_cycle = %d, ticks_per_sec = %d\n", + *(unsigned int *)RETX_MIB_TIMER_CFG, RETX_MIB_TIMER_CFG->tick_cycle, RETX_MIB_TIMER_CFG->ticks_per_sec); + + *eof = 1; + + return len; +} + +static int proc_write_retx_cfg(struct file *file, const char *buf, unsigned long count, void *data) +{ + char *p1, *p2; + int len; + int colon; + char local_buf[1024]; + char *tokens[4] = {0}; + unsigned int token_num = 0; + + len = sizeof(local_buf) < count ? sizeof(local_buf) - 1 : count; + len = len - copy_from_user(local_buf, buf, len); + local_buf[len] = 0; + + p1 = local_buf; + colon = 0; + while ( token_num < NUM_ENTITY(tokens) && get_token(&p1, &p2, &len, &colon) ) { + tokens[token_num++] = p1; + + p1 = p2; + } + + if ( token_num > 0 ) { + if ( stricmp(tokens[0], "help") == 0 ) { + printk("echo help > /proc/driver/ifx_atm/retx_cfg ==> \n\tprint this help message\n\n"); + + printk("echo set retx <enable|disable|0|1|on|off> > /proc/driver/ifx_atm/retx_cfg\n"); + printk("\t:enable or disable retx feature\n\n"); + + printk("echo set <td_max|td_min|fw_alpha|sync_inp|invld_range|buff_size> <number> > /proc/driver/ifx_atm/retx_cfg\n"); + printk("\t: set td_max, td_min, fw_alpha, sync_inp, invalid_range, buff_size\n\n"); + + printk("echo set <service_header|service_mask> <hex_number> /proc/driver/ifx_atm/retx_cfg \n"); + printk("\t: set service_header, service_mask\n\n"); + } + else if ( stricmp(tokens[0], "set") == 0 && token_num >= 3 ) { + + if ( stricmp(tokens[1], "retx") == 0 ) { + if ( stricmp(tokens[2], "enable") == 0 || + stricmp(tokens[2], "on") == 0 || + stricmp(tokens[2], "1") == 0 ) + RETX_MODE_CFG->retx_en = 1; + else if ( stricmp(tokens[2], "disable") == 0 || + stricmp(tokens[2], "off") == 0 || + stricmp(tokens[2], "0") == 0 ) + RETX_MODE_CFG->retx_en = 0; + printk("RETX_MODE_CFG->retx_en - %d\n", RETX_MODE_CFG->retx_en); + } + else { + unsigned int dec_val, hex_val; + + p1 = tokens[2]; + dec_val = (unsigned int)get_number(&p1, NULL, 0); + p2 = tokens[2]; + hex_val = (unsigned int)get_number(&p2, NULL, 1); + + if ( *p2 == 0 ) { + if ( stricmp(tokens[1], "service_header") == 0 ) { + *RETX_SERVICE_HEADER_CFG = hex_val; + printk("RETX_SERVICE_HEADER_CFG - 0x%08x\n", *RETX_SERVICE_HEADER_CFG); + } + else if ( stricmp(tokens[1], "service_mask") == 0 ) { + *RETX_MASK_HEADER_CFG = hex_val; + printk("RETX_MASK_HEADER_CFG - 0x%08x\n", *RETX_MASK_HEADER_CFG); + } + } + if ( *p1 == 0 ) { + if ( stricmp(tokens[1], "td_max") == 0 ) { + (unsigned int)RETX_TD_CFG->td_max = (dec_val >= 0xff ? 0Xff : dec_val); + printk("RETX_TD_CFG->td_max - %d\n", RETX_TD_CFG->td_max); + } + else if ( stricmp(tokens[1], "td_min") == 0 ) { + (unsigned int)RETX_TD_CFG->td_min = (dec_val >= 0xff ? 0Xff : dec_val); + printk("RETX_TD_CFG->td_min - %d\n", RETX_TD_CFG->td_min); + } + else if ( stricmp(tokens[1], "fw_alpha") == 0 ) { + RETX_TSYNC_CFG->fw_alpha = dec_val >= 0x7FFE ? 0X7EEE : dec_val; + printk("RETX_TSYNC_CFG->fw_alpha - %d\n", RETX_TSYNC_CFG->fw_alpha); + } + else if ( stricmp(tokens[1], "sync_inp") == 0 ) { + RETX_TSYNC_CFG->sync_inp = dec_val >= 0x7FFE ? 0X7EEE : dec_val; + printk("RETX_TSYNC_CFG->sync_inp - %d\n", RETX_TSYNC_CFG->sync_inp); + } + else if ( stricmp(tokens[1], "invld_range") == 0 ) { + RETX_MODE_CFG->invld_range = dec_val >= 250 ? 250 : dec_val; + printk("RETX_MODE_CFG->invld_range - %d\n", RETX_MODE_CFG->invld_range); + } + else if ( stricmp(tokens[1], "buff_size") == 0 ) { + dec_val = (dec_val + 31) / 32; + RETX_MODE_CFG->buff_size = dec_val >= 4096 / 32 ? 4096 / 32 : dec_val; + printk("RETX_MODE_CFG->buff_size - %d\n", RETX_MODE_CFG->buff_size); + } + } + } + + } + } + + return count; +} + +static int proc_read_retx_dsl_param(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page + off + len, "DSL Param [timestamp %ld.%ld]:\n", g_retx_polling_start.tv_sec, g_retx_polling_start.tv_usec); + + if ( g_xdata_addr == NULL ) + len += sprintf(page + off + len, " DSL parameters not available !\n"); + else { + volatile struct dsl_param *p_dsl_param = (volatile struct dsl_param *)g_xdata_addr; + + len += sprintf(page + off + len, " update_flag = %u\n", p_dsl_param->update_flag); + len += sprintf(page + off + len, " MinDelayrt = %u\n", p_dsl_param->MinDelayrt); + len += sprintf(page + off + len, " MaxDelayrt = %u\n", p_dsl_param->MaxDelayrt); + len += sprintf(page + off + len, " RetxEnable = %u\n", p_dsl_param->RetxEnable); + len += sprintf(page + off + len, " ServiceSpecificReTx = %u\n", p_dsl_param->ServiceSpecificReTx); + len += sprintf(page + off + len, " ReTxPVC = 0x%08x\n", p_dsl_param->ReTxPVC); + len += sprintf(page + off + len, " RxDtuCorruptedCNT = %u\n", p_dsl_param->RxDtuCorruptedCNT); + len += sprintf(page + off + len, " RxRetxDtuUnCorrectedCNT = %u\n", p_dsl_param->RxRetxDtuUnCorrectedCNT); + len += sprintf(page + off + len, " RxLastEFB = %u\n", p_dsl_param->RxLastEFB); + len += sprintf(page + off + len, " RxDtuCorrectedCNT = %u\n", p_dsl_param->RxDtuCorrectedCNT); + } + if ( g_retx_polling_end.tv_sec != 0 || g_retx_polling_end.tv_usec != 0 ) { + unsigned long polling_time_usec; + + polling_time_usec = (g_retx_polling_end.tv_sec - g_retx_polling_start.tv_sec) * 1000000 + (g_retx_polling_end.tv_usec - g_retx_polling_start.tv_usec); + len += sprintf(page + off + len, "DSL Param Update Time: %lu.%03lums\n", polling_time_usec / 1000, polling_time_usec % 1000); + } + + return len; +} + + #endif + +#endif + +static int stricmp(const char *p1, const char *p2) +{ + int c1, c2; + + while ( *p1 && *p2 ) { + c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1; + c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2; + if ( (c1 -= c2) ) + return c1; + p1++; + p2++; + } + + return *p1 - *p2; +} + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + +static int strincmp(const char *p1, const char *p2, int n) +{ + int c1 = 0, c2; + + while ( n && *p1 && *p2 ) { + c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1; + c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2; + if ( (c1 -= c2) ) + return c1; + p1++; + p2++; + n--; + } + + return n ? *p1 - *p2 : c1; +} + +static int get_token(char **p1, char **p2, int *len, int *colon) +{ + int tlen = 0; + + while ( *len && !((**p1 >= 'A' && **p1 <= 'Z') || (**p1 >= 'a' && **p1<= 'z') || (**p1 >= '0' && **p1<= '9')) ) + { + (*p1)++; + (*len)--; + } + if ( !*len ) + return 0; + + if ( *colon ) + { + *colon = 0; + *p2 = *p1; + while ( *len && **p2 > ' ' && **p2 != ',' ) + { + if ( **p2 == ':' ) + { + *colon = 1; + break; + } + (*p2)++; + (*len)--; + tlen++; + } + **p2 = 0; + } + else + { + *p2 = *p1; + while ( *len && **p2 > ' ' && **p2 != ',' ) + { + (*p2)++; + (*len)--; + tlen++; + } + **p2 = 0; + } + + return tlen; +} + +static unsigned int get_number(char **p, int *len, int is_hex) +{ + unsigned int ret = 0; + unsigned int n = 0; + + if ( (*p)[0] == '0' && (*p)[1] == 'x' ) + { + is_hex = 1; + (*p) += 2; + if ( len ) + (*len) -= 2; + } + + if ( is_hex ) + { + while ( (!len || *len) && ((**p >= '0' && **p <= '9') || (**p >= 'a' && **p <= 'f') || (**p >= 'A' && **p <= 'F')) ) + { + if ( **p >= '0' && **p <= '9' ) + n = **p - '0'; + else if ( **p >= 'a' && **p <= 'f' ) + n = **p - 'a' + 10; + else if ( **p >= 'A' && **p <= 'F' ) + n = **p - 'A' + 10; + ret = (ret << 4) | n; + (*p)++; + if ( len ) + (*len)--; + } + } + else + { + while ( (!len || *len) && **p >= '0' && **p <= '9' ) + { + n = **p - '0'; + ret = ret * 10 + n; + (*p)++; + if ( len ) + (*len)--; + } + } + + return ret; +} + +static void ignore_space(char **p, int *len) +{ + while ( *len && (**p <= ' ' || **p == ':' || **p == '.' || **p == ',') ) + { + (*p)++; + (*len)--; + } +} + +#endif + +static INLINE int ifx_atm_version(char *buf) +{ + int len = 0; + unsigned int major, minor; + + ifx_atm_get_fw_ver(&major, &minor); + + len += sprintf(buf + len, " ATM (A1) firmware version %d.%d.%d\n", IFX_ATM_VER_MAJOR, IFX_ATM_VER_MID,IFX_ATM_VER_MINOR); + + return len; +} + +static INLINE void check_parameters(void) +{ + /* Please refer to Amazon spec 15.4 for setting these values. */ + if ( qsb_tau < 1 ) + qsb_tau = 1; + if ( qsb_tstep < 1 ) + qsb_tstep = 1; + else if ( qsb_tstep > 4 ) + qsb_tstep = 4; + else if ( qsb_tstep == 3 ) + qsb_tstep = 2; + + /* There is a delay between PPE write descriptor and descriptor is */ + /* really stored in memory. Host also has this delay when writing */ + /* descriptor. So PPE will use this value to determine if the write */ + /* operation makes effect. */ + if ( write_descriptor_delay < 0 ) + write_descriptor_delay = 0; + + if ( aal5_fill_pattern < 0 ) + aal5_fill_pattern = 0; + else + aal5_fill_pattern &= 0xFF; + + /* Because of the limitation of length field in descriptors, the packet */ + /* size could not be larger than 64K minus overhead size. */ + if ( aal5r_max_packet_size < 0 ) + aal5r_max_packet_size = 0; + else if ( aal5r_max_packet_size >= 65535 - MAX_RX_FRAME_EXTRA_BYTES ) + aal5r_max_packet_size = 65535 - MAX_RX_FRAME_EXTRA_BYTES; + if ( aal5r_min_packet_size < 0 ) + aal5r_min_packet_size = 0; + else if ( aal5r_min_packet_size > aal5r_max_packet_size ) + aal5r_min_packet_size = aal5r_max_packet_size; + if ( aal5s_max_packet_size < 0 ) + aal5s_max_packet_size = 0; + else if ( aal5s_max_packet_size >= 65535 - MAX_TX_FRAME_EXTRA_BYTES ) + aal5s_max_packet_size = 65535 - MAX_TX_FRAME_EXTRA_BYTES; + if ( aal5s_min_packet_size < 0 ) + aal5s_min_packet_size = 0; + else if ( aal5s_min_packet_size > aal5s_max_packet_size ) + aal5s_min_packet_size = aal5s_max_packet_size; + + if ( dma_rx_descriptor_length < 2 ) + dma_rx_descriptor_length = 2; + if ( dma_tx_descriptor_length < 2 ) + dma_tx_descriptor_length = 2; + if ( dma_rx_clp1_descriptor_threshold < 0 ) + dma_rx_clp1_descriptor_threshold = 0; + else if ( dma_rx_clp1_descriptor_threshold > dma_rx_descriptor_length ) + dma_rx_clp1_descriptor_threshold = dma_rx_descriptor_length; + + if ( dma_tx_descriptor_length < 2 ) + dma_tx_descriptor_length = 2; +} + +static INLINE int init_priv_data(void) +{ + void *p; + int i; + struct rx_descriptor rx_desc = {0}; + struct sk_buff *skb; + volatile struct tx_descriptor *p_tx_desc; + struct sk_buff **ppskb; + + // clear atm private data structure + memset(&g_atm_priv_data, 0, sizeof(g_atm_priv_data)); + + // allocate memory for RX (AAL) descriptors + p = kzalloc(dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL); + if ( p == NULL ) + return IFX_ERROR; + dma_cache_wback_inv((unsigned long)p, dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT); + g_atm_priv_data.aal_desc_base = p; + p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1); + g_atm_priv_data.aal_desc = (volatile struct rx_descriptor *)p; + + // allocate memory for RX (OAM) descriptors + p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL); + if ( p == NULL ) + return IFX_ERROR; + dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT); + g_atm_priv_data.oam_desc_base = p; + p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1); + g_atm_priv_data.oam_desc = (volatile struct rx_descriptor *)p; + + // allocate memory for RX (OAM) buffer + p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT, GFP_KERNEL); + if ( p == NULL ) + return IFX_ERROR; + dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT); + g_atm_priv_data.oam_buf_base = p; + p = (void *)(((unsigned int)p + DATA_BUFFER_ALIGNMENT - 1) & ~(DATA_BUFFER_ALIGNMENT - 1)); + g_atm_priv_data.oam_buf = p; + + // allocate memory for TX descriptors + p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL); + if ( p == NULL ) + return IFX_ERROR; + dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT); + g_atm_priv_data.tx_desc_base = p; + + // allocate memory for TX skb pointers + p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4, GFP_KERNEL); + if ( p == NULL ) + return IFX_ERROR; + dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4); + g_atm_priv_data.tx_skb_base = p; + + // setup RX (AAL) descriptors + rx_desc.own = 1; + rx_desc.c = 0; + rx_desc.sop = 1; + rx_desc.eop = 1; + rx_desc.byteoff = 0; + rx_desc.id = 0; + rx_desc.err = 0; + rx_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE; + for ( i = 0; i < dma_rx_descriptor_length; i++ ) { + skb = alloc_skb_rx(); + if ( skb == NULL ) + return IFX_ERROR; + rx_desc.dataptr = ((unsigned int)skb->data >> 2) & 0x0FFFFFFF; + g_atm_priv_data.aal_desc[i] = rx_desc; + } + + // setup RX (OAM) descriptors + p = (void *)((unsigned int)g_atm_priv_data.oam_buf | KSEG1); + rx_desc.own = 1; + rx_desc.c = 0; + rx_desc.sop = 1; + rx_desc.eop = 1; + rx_desc.byteoff = 0; + rx_desc.id = 0; + rx_desc.err = 0; + rx_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE; + for ( i = 0; i < RX_DMA_CH_OAM_DESC_LEN; i++ ) { + rx_desc.dataptr = ((unsigned int)p >> 2) & 0x0FFFFFFF; + g_atm_priv_data.oam_desc[i] = rx_desc; + p = (void *)((unsigned int)p + RX_DMA_CH_OAM_BUF_SIZE); + } + + // setup TX descriptors and skb pointers + p_tx_desc = (volatile struct tx_descriptor *)((((unsigned int)g_atm_priv_data.tx_desc_base + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1); + ppskb = (struct sk_buff **)(((unsigned int)g_atm_priv_data.tx_skb_base + 3) & ~3); + for ( i = 0; i < MAX_PVC_NUMBER; i++ ) { + g_atm_priv_data.conn[i].tx_desc = &p_tx_desc[i * dma_tx_descriptor_length]; + g_atm_priv_data.conn[i].tx_skb = &ppskb[i * dma_tx_descriptor_length]; + } + + for ( i = 0; i < ATM_PORT_NUMBER; i++ ) + g_atm_priv_data.port[i].tx_max_cell_rate = DEFAULT_TX_LINK_RATE; + + return IFX_SUCCESS; +} + +static INLINE void clear_priv_data(void) +{ + int i, j; + struct sk_buff *skb; + + for ( i = 0; i < MAX_PVC_NUMBER; i++ ) { + if ( g_atm_priv_data.conn[i].tx_skb != NULL ) { + for ( j = 0; j < dma_tx_descriptor_length; j++ ) + if ( g_atm_priv_data.conn[i].tx_skb[j] != NULL ) + dev_kfree_skb_any(g_atm_priv_data.conn[i].tx_skb[j]); + } + } + + if ( g_atm_priv_data.tx_skb_base != NULL ) + kfree(g_atm_priv_data.tx_skb_base); + + if ( g_atm_priv_data.tx_desc_base != NULL ) + kfree(g_atm_priv_data.tx_desc_base); + + if ( g_atm_priv_data.oam_buf_base != NULL ) + kfree(g_atm_priv_data.oam_buf_base); + + if ( g_atm_priv_data.oam_desc_base != NULL ) + kfree(g_atm_priv_data.oam_desc_base); + + if ( g_atm_priv_data.aal_desc_base != NULL ) { + for ( i = 0; i < dma_rx_descriptor_length; i++ ) { + if ( g_atm_priv_data.aal_desc[i].sop || g_atm_priv_data.aal_desc[i].eop ) { // descriptor initialized + skb = get_skb_rx_pointer(g_atm_priv_data.aal_desc[i].dataptr); + dev_kfree_skb_any(skb); + } + } + kfree(g_atm_priv_data.aal_desc_base); + } +} + +static INLINE void init_rx_tables(void) +{ + int i; + struct wrx_queue_config wrx_queue_config = {0}; + struct wrx_dma_channel_config wrx_dma_channel_config = {0}; + struct htu_entry htu_entry = {0}; + struct htu_result htu_result = {0}; + struct htu_mask htu_mask = { set: 0x01, + clp: 0x01, + pid_mask: 0x00, + vpi_mask: 0x00, + vci_mask: 0x00, + pti_mask: 0x00, + clear: 0x00}; + + /* + * General Registers + */ + *CFG_WRX_HTUTS = MAX_PVC_NUMBER + OAM_HTU_ENTRY_NUMBER; +#ifndef CONFIG_AMAZON_SE + *CFG_WRX_QNUM = MAX_QUEUE_NUMBER; +#endif + *CFG_WRX_DCHNUM = RX_DMA_CH_TOTAL; + *WRX_DMACH_ON = (1 << RX_DMA_CH_TOTAL) - 1; + *WRX_HUNT_BITTH = DEFAULT_RX_HUNT_BITTH; + + /* + * WRX Queue Configuration Table + */ + wrx_queue_config.uumask = 0; + wrx_queue_config.cpimask = 0; + wrx_queue_config.uuexp = 0; + wrx_queue_config.cpiexp = 0; + wrx_queue_config.mfs = aal5r_max_packet_size; + wrx_queue_config.oversize = aal5r_max_packet_size; + wrx_queue_config.undersize = aal5r_min_packet_size; + wrx_queue_config.errdp = aal5r_drop_error_packet; + wrx_queue_config.dmach = RX_DMA_CH_AAL; + for ( i = 0; i < MAX_QUEUE_NUMBER; i++ ) + *WRX_QUEUE_CONFIG(i) = wrx_queue_config; + WRX_QUEUE_CONFIG(OAM_RX_QUEUE)->dmach = RX_DMA_CH_OAM; + + /* + * WRX DMA Channel Configuration Table + */ + wrx_dma_channel_config.chrl = 0; + wrx_dma_channel_config.clp1th = dma_rx_clp1_descriptor_threshold; + wrx_dma_channel_config.mode = 0; + wrx_dma_channel_config.rlcfg = 0; + + wrx_dma_channel_config.deslen = RX_DMA_CH_OAM_DESC_LEN; + wrx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.oam_desc >> 2) & 0x0FFFFFFF; + *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM) = wrx_dma_channel_config; + + wrx_dma_channel_config.deslen = dma_rx_descriptor_length; + wrx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.aal_desc >> 2) & 0x0FFFFFFF; + *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL) = wrx_dma_channel_config; + + /* + * HTU Tables + */ + for ( i = 0; i < MAX_PVC_NUMBER; i++ ) + { + htu_result.qid = (unsigned int)i; + + *HTU_ENTRY(i + OAM_HTU_ENTRY_NUMBER) = htu_entry; + *HTU_MASK(i + OAM_HTU_ENTRY_NUMBER) = htu_mask; + *HTU_RESULT(i + OAM_HTU_ENTRY_NUMBER) = htu_result; + } + /* OAM HTU Entry */ + htu_entry.vci = 0x03; + htu_mask.pid_mask = 0x03; + htu_mask.vpi_mask = 0xFF; + htu_mask.vci_mask = 0x0000; + htu_mask.pti_mask = 0x07; + htu_result.cellid = OAM_RX_QUEUE; + htu_result.type = 1; + htu_result.ven = 1; + htu_result.qid = OAM_RX_QUEUE; + *HTU_RESULT(OAM_F4_SEG_HTU_ENTRY) = htu_result; + *HTU_MASK(OAM_F4_SEG_HTU_ENTRY) = htu_mask; + *HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY) = htu_entry; + htu_entry.vci = 0x04; + htu_result.cellid = OAM_RX_QUEUE; + htu_result.type = 1; + htu_result.ven = 1; + htu_result.qid = OAM_RX_QUEUE; + *HTU_RESULT(OAM_F4_TOT_HTU_ENTRY) = htu_result; + *HTU_MASK(OAM_F4_TOT_HTU_ENTRY) = htu_mask; + *HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY) = htu_entry; + htu_entry.vci = 0x00; + htu_entry.pti = 0x04; + htu_mask.vci_mask = 0xFFFF; + htu_mask.pti_mask = 0x01; + htu_result.cellid = OAM_RX_QUEUE; + htu_result.type = 1; + htu_result.ven = 1; + htu_result.qid = OAM_RX_QUEUE; + *HTU_RESULT(OAM_F5_HTU_ENTRY) = htu_result; + *HTU_MASK(OAM_F5_HTU_ENTRY) = htu_mask; + *HTU_ENTRY(OAM_F5_HTU_ENTRY) = htu_entry; +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + htu_entry.pid = 0x0; + htu_entry.vpi = 0x01; + htu_entry.vci = 0x0001; + htu_entry.pti = 0x00; + htu_mask.pid_mask = 0x0; + htu_mask.vpi_mask = 0x00; + htu_mask.vci_mask = 0x0000; + htu_mask.pti_mask = 0x3; + htu_result.cellid = OAM_RX_QUEUE; + htu_result.type = 1; + htu_result.ven = 1; + htu_result.qid = OAM_RX_QUEUE; + *HTU_RESULT(OAM_ARQ_HTU_ENTRY) = htu_result; + *HTU_MASK(OAM_ARQ_HTU_ENTRY) = htu_mask; + *HTU_ENTRY(OAM_ARQ_HTU_ENTRY) = htu_entry; +#endif +} + +static INLINE void init_tx_tables(void) +{ + int i; + struct wtx_queue_config wtx_queue_config = {0}; + struct wtx_dma_channel_config wtx_dma_channel_config = {0}; + struct wtx_port_config wtx_port_config = { res1: 0, + qid: 0, + qsben: 1}; + + /* + * General Registers + */ + *CFG_WTX_DCHNUM = MAX_TX_DMA_CHANNEL_NUMBER; + *WTX_DMACH_ON = ((1 << MAX_TX_DMA_CHANNEL_NUMBER) - 1) ^ ((1 << FIRST_QSB_QID) - 1); + *CFG_WRDES_DELAY = write_descriptor_delay; + + /* + * WTX Port Configuration Table + */ + for ( i = 0; i < ATM_PORT_NUMBER; i++ ) + *WTX_PORT_CONFIG(i) = wtx_port_config; + + /* + * WTX Queue Configuration Table + */ + wtx_queue_config.qsben = 1; + wtx_queue_config.sbid = 0; + for ( i = 0; i < MAX_TX_DMA_CHANNEL_NUMBER; i++ ) { + wtx_queue_config.qsb_vcid = i; + *WTX_QUEUE_CONFIG(i) = wtx_queue_config; + } + + /* + * WTX DMA Channel Configuration Table + */ + wtx_dma_channel_config.mode = 0; + wtx_dma_channel_config.deslen = 0; + wtx_dma_channel_config.desba = 0; + for ( i = 0; i < FIRST_QSB_QID; i++ ) + *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config; + /* normal connection */ + wtx_dma_channel_config.deslen = dma_tx_descriptor_length; + for ( ; i < MAX_TX_DMA_CHANNEL_NUMBER ; i++ ) { + wtx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.conn[i - FIRST_QSB_QID].tx_desc >> 2) & 0x0FFFFFFF; + *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config; + } +} + + + +/* + * #################################### + * Global Function + * #################################### + */ + +static int atm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr) +{ + int i, j; + + ASSERT(port_cell != NULL, "port_cell is NULL"); + ASSERT(xdata_addr != NULL, "xdata_addr is NULL"); + + for ( j = 0; j < ATM_PORT_NUMBER && j < port_cell->port_num; j++ ) + if ( port_cell->tx_link_rate[j] > 0 ) + break; + for ( i = 0; i < ATM_PORT_NUMBER && i < port_cell->port_num; i++ ) + g_atm_priv_data.port[i].tx_max_cell_rate = port_cell->tx_link_rate[i] > 0 ? port_cell->tx_link_rate[i] : port_cell->tx_link_rate[j]; + + qsb_global_set(); + + for ( i = 0; i < MAX_PVC_NUMBER; i++ ) + if ( g_atm_priv_data.conn[i].vcc != NULL ) + set_qsb(g_atm_priv_data.conn[i].vcc, &g_atm_priv_data.conn[i].vcc->qos, i); + + // TODO: ReTX set xdata_addr + g_xdata_addr = xdata_addr; + + g_showtime = 1; + +#if defined(CONFIG_VR9) + IFX_REG_W32(0x0F, UTP_CFG); +#endif + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + if ( !timer_pending(&g_retx_polling_timer) ) { + g_retx_polling_cnt = HZ; + g_retx_polling_timer.expires = jiffies + RETX_POLLING_INTERVAL; + add_timer(&g_retx_polling_timer); + } +#endif + + //printk("enter showtime, cell rate: 0 - %d, 1 - %d, xdata addr: 0x%08x\n", g_atm_priv_data.port[0].tx_max_cell_rate, g_atm_priv_data.port[1].tx_max_cell_rate, (unsigned int)g_xdata_addr); + + return IFX_SUCCESS; +} + +static int atm_showtime_exit(void) +{ + if ( !g_showtime ) + return IFX_ERROR; + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + RETX_MODE_CFG->retx_en = 0; // disable ReTX + del_timer(&g_retx_polling_timer); +#endif + +#if defined(CONFIG_VR9) + IFX_REG_W32(0x00, UTP_CFG); +#endif + + g_showtime = 0; + + // TODO: ReTX clean state + g_xdata_addr = NULL; + + printk("leave showtime\n"); + + return IFX_SUCCESS; +} + + + +/* + * #################################### + * Init/Cleanup API + * #################################### + */ + +/* + * Description: + * Initialize global variables, PP32, comunication structures, register IRQ + * and register device. + * Input: + * none + * Output: + * 0 --- successful + * else --- failure, usually it is negative value of error code + */ +static int __devinit ifx_atm_init(void) +{ + int ret; + int port_num; + struct port_cell_info port_cell = {0}; + int i, j; + char ver_str[256]; + + check_parameters(); + + ret = init_priv_data(); + if ( ret != IFX_SUCCESS ) { + err("INIT_PRIV_DATA_FAIL"); + goto INIT_PRIV_DATA_FAIL; + } + + ifx_atm_init_chip(); + init_rx_tables(); + init_tx_tables(); + + /* create devices */ + for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", &g_ifx_atm_ops, -1, NULL); +#else + g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL); +#endif + + if ( !g_atm_priv_data.port[port_num].dev ) { + err("failed to register atm device %d!", port_num); + ret = -EIO; + goto ATM_DEV_REGISTER_FAIL; + } + else { + g_atm_priv_data.port[port_num].dev->ci_range.vpi_bits = 8; + g_atm_priv_data.port[port_num].dev->ci_range.vci_bits = 16; + g_atm_priv_data.port[port_num].dev->link_rate = g_atm_priv_data.port[port_num].tx_max_cell_rate; + g_atm_priv_data.port[port_num].dev->dev_data = (void*)port_num; + } + } + + /* register interrupt handler */ + ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "atm_mailbox_isr", &g_atm_priv_data); + if ( ret ) { + if ( ret == -EBUSY ) { + err("IRQ may be occupied by other driver, please reconfig to disable it."); + } + else { + err("request_irq fail"); + } + goto REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL; + } + disable_irq(PPE_MAILBOX_IGU1_INT); + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + init_atm_tc_retrans_param(); + + init_timer(&g_retx_polling_timer); + g_retx_polling_timer.function = retx_polling_func; +#endif + + ret = ifx_pp32_start(0); + if ( ret ) { + err("ifx_pp32_start fail!"); + goto PP32_START_FAIL; + } + + port_cell.port_num = ATM_PORT_NUMBER; + if( !IS_ERR(&ifx_mei_atm_showtime_check) && &ifx_mei_atm_showtime_check) + ifx_mei_atm_showtime_check(&g_showtime, &port_cell, &g_xdata_addr); + if ( g_showtime ) { + for ( i = 0; i < ATM_PORT_NUMBER; i++ ) + if ( port_cell.tx_link_rate[i] != 0 ) + break; + for ( j = 0; j < ATM_PORT_NUMBER; j++ ) + g_atm_priv_data.port[j].tx_max_cell_rate = port_cell.tx_link_rate[j] != 0 ? port_cell.tx_link_rate[j] : port_cell.tx_link_rate[i]; + } + + qsb_global_set(); + validate_oam_htu_entry(); + +#if 0 /*defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK*/ + ifx_led_trigger_register("dsl_data", &g_data_led_trigger); +#endif + + /* create proc file */ + proc_file_create(); + + if( !IS_ERR(&ifx_mei_atm_showtime_enter) && &ifx_mei_atm_showtime_enter ) + ifx_mei_atm_showtime_enter = atm_showtime_enter; + + if( !IS_ERR(&ifx_mei_atm_showtime_exit) && !ifx_mei_atm_showtime_exit ) + ifx_mei_atm_showtime_exit = atm_showtime_exit; + + ifx_atm_version(ver_str); + printk(KERN_INFO "%s", ver_str); + + printk("ifxmips_atm: ATM init succeed\n"); + + return IFX_SUCCESS; + +PP32_START_FAIL: + free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data); +REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL: +ATM_DEV_REGISTER_FAIL: + while ( port_num-- > 0 ) + atm_dev_deregister(g_atm_priv_data.port[port_num].dev); +INIT_PRIV_DATA_FAIL: + clear_priv_data(); + printk("ifxmips_atm: ATM init failed\n"); + return ret; +} + +/* + * Description: + * Release memory, free IRQ, and deregister device. + * Input: + * none + * Output: + * none + */ +static void __exit ifx_atm_exit(void) +{ + int port_num; + + if( !IS_ERR(&ifx_mei_atm_showtime_enter) && &ifx_mei_atm_showtime_enter ) + ifx_mei_atm_showtime_enter = NULL; + if( !IS_ERR(&ifx_mei_atm_showtime_exit) && !ifx_mei_atm_showtime_exit ) + ifx_mei_atm_showtime_exit = NULL; + + proc_file_delete(); + +#if 0 /*defined(ENABLE_LED_FRAMEWORK) && ENABLE_LED_FRAMEWORK*/ + ifx_led_trigger_deregister(g_data_led_trigger); + g_data_led_trigger = NULL; +#endif + + invalidate_oam_htu_entry(); + + ifx_pp32_stop(0); + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + del_timer(&g_retx_polling_timer); + clear_atm_tc_retrans_param(); +#endif + + free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data); + + for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) + atm_dev_deregister(g_atm_priv_data.port[port_num].dev); + + ifx_atm_uninit_chip(); + + clear_priv_data(); +} + +module_init(ifx_atm_init); +module_exit(ifx_atm_exit); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/package/system/ltq-dsl/src/ifxmips_atm_core.h b/package/system/ltq-dsl/src/ifxmips_atm_core.h new file mode 100644 index 0000000000..e566039552 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_core.h @@ -0,0 +1,271 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_core.h +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver header file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 17 JUN 2009 Xu Liang Init Version +*******************************************************************************/ + +#ifndef IFXMIPS_ATM_CORE_H +#define IFXMIPS_ATM_CORE_H + + +#include "ifxmips_compat.h" +#include "ifx_atm.h" +#include "ifxmips_atm_ppe_common.h" +#include "ifxmips_atm_fw_regs_common.h" + + + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * Compile Options + */ + +#define ENABLE_DEBUG 1 + +#define ENABLE_ASSERT 1 + +#define INLINE + +#define DEBUG_DUMP_SKB 1 + +#define DEBUG_QOS 1 + +#define DISABLE_QOS_WORKAROUND 0 + +#define ENABLE_DBG_PROC 1 + +#define ENABLE_FW_PROC 1 + +#ifdef CONFIG_IFX_ATM_TASKLET + #define ENABLE_TASKLET 1 +#endif + +#ifdef CONFIG_IFX_ATM_RETX + #define ENABLE_ATM_RETX 1 +#endif + +#if defined(CONFIG_DSL_MEI_CPE_DRV) && !defined(CONFIG_IFXMIPS_DSL_CPE_MEI) + #define CONFIG_IFXMIPS_DSL_CPE_MEI 1 +#endif + +/* + * Debug/Assert/Error Message + */ + +#define DBG_ENABLE_MASK_ERR (1 << 0) +#define DBG_ENABLE_MASK_DEBUG_PRINT (1 << 1) +#define DBG_ENABLE_MASK_ASSERT (1 << 2) +#define DBG_ENABLE_MASK_DUMP_SKB_RX (1 << 8) +#define DBG_ENABLE_MASK_DUMP_SKB_TX (1 << 9) +#define DBG_ENABLE_MASK_DUMP_QOS (1 << 10) +#define DBG_ENABLE_MASK_DUMP_INIT (1 << 11) +#define DBG_ENABLE_MASK_MAC_SWAP (1 << 12) +#define DBG_ENABLE_MASK_ALL (DBG_ENABLE_MASK_ERR | DBG_ENABLE_MASK_DEBUG_PRINT | DBG_ENABLE_MASK_ASSERT | DBG_ENABLE_MASK_DUMP_SKB_RX | DBG_ENABLE_MASK_DUMP_SKB_TX | DBG_ENABLE_MASK_DUMP_QOS | DBG_ENABLE_MASK_DUMP_INIT | DBG_ENABLE_MASK_MAC_SWAP) + +#define err(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 ) + +#if defined(ENABLE_DEBUG) && ENABLE_DEBUG + #undef dbg + #define dbg(format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT) ) printk(KERN_WARNING __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 ) +#else + #if !defined(dbg) + #define dbg(format, arg...) + #endif +#endif + +#if defined(ENABLE_ASSERT) && ENABLE_ASSERT + #define ASSERT(cond, format, arg...) do { if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT) && !(cond) ) printk(KERN_ERR __FILE__ ":%d:%s: " format "\n", __LINE__, __FUNCTION__, ##arg); } while ( 0 ) +#else + #define ASSERT(cond, format, arg...) +#endif + + +/* + * Constants + */ +#define DEFAULT_TX_LINK_RATE 3200 // in cells + +/* + * ATM Port, QSB Queue, DMA RX/TX Channel Parameters + */ +#define ATM_PORT_NUMBER 2 +#define MAX_QUEUE_NUMBER 16 +#define OAM_RX_QUEUE 15 +#define QSB_RESERVE_TX_QUEUE 0 +#define FIRST_QSB_QID 1 +#define MAX_PVC_NUMBER (MAX_QUEUE_NUMBER - FIRST_QSB_QID) +#define MAX_RX_DMA_CHANNEL_NUMBER 8 +#define MAX_TX_DMA_CHANNEL_NUMBER 16 +#define DATA_BUFFER_ALIGNMENT EMA_ALIGNMENT +#define DESC_ALIGNMENT 8 +#define DEFAULT_RX_HUNT_BITTH 4 + +/* + * RX DMA Channel Allocation + */ +#define RX_DMA_CH_OAM 0 +#define RX_DMA_CH_AAL 1 +#define RX_DMA_CH_TOTAL 2 +#define RX_DMA_CH_OAM_DESC_LEN 32 +#define RX_DMA_CH_OAM_BUF_SIZE (CELL_SIZE & ~15) +#define RX_DMA_CH_AAL_BUF_SIZE (2048 - 48) + +/* + * OAM Constants + */ +#define OAM_HTU_ENTRY_NUMBER 3 +#define OAM_F4_SEG_HTU_ENTRY 0 +#define OAM_F4_TOT_HTU_ENTRY 1 +#define OAM_F5_HTU_ENTRY 2 +#define OAM_F4_CELL_ID 0 +#define OAM_F5_CELL_ID 15 +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + #undef OAM_HTU_ENTRY_NUMBER + #define OAM_HTU_ENTRY_NUMBER 4 + #define OAM_ARQ_HTU_ENTRY 3 +#endif + +/* + * RX Frame Definitions + */ +#define MAX_RX_PACKET_ALIGN_BYTES 3 +#define MAX_RX_PACKET_PADDING_BYTES 3 +#define RX_INBAND_TRAILER_LENGTH 8 +#define MAX_RX_FRAME_EXTRA_BYTES (RX_INBAND_TRAILER_LENGTH + MAX_RX_PACKET_ALIGN_BYTES + MAX_RX_PACKET_PADDING_BYTES) + +/* + * TX Frame Definitions + */ +#define MAX_TX_HEADER_ALIGN_BYTES 12 +#define MAX_TX_PACKET_ALIGN_BYTES 3 +#define MAX_TX_PACKET_PADDING_BYTES 3 +#define TX_INBAND_HEADER_LENGTH 8 +#define MAX_TX_FRAME_EXTRA_BYTES (TX_INBAND_HEADER_LENGTH + MAX_TX_HEADER_ALIGN_BYTES + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES) + +/* + * Cell Constant + */ +#define CELL_SIZE ATM_AAL0_SDU + +/* + * ReTX Constant + */ +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + #define RETX_PLAYOUT_BUFFER_ORDER 6 + #define RETX_PLAYOUT_BUFFER_SIZE (PAGE_SIZE * (1 << RETX_PLAYOUT_BUFFER_ORDER)) + #define RETX_PLAYOUT_FW_BUFF_SIZE (RETX_PLAYOUT_BUFFER_SIZE / (32 * 56 /* cell size */)) + #define RETX_POLLING_INTERVAL (HZ / 100 > 0 ? HZ / 100 : 1) +#endif + + + +/* + * #################################### + * Data Type + * #################################### + */ + +typedef struct { + unsigned int h; + unsigned int l; +} ppe_u64_t; + +struct port { + unsigned int tx_max_cell_rate; + unsigned int tx_current_cell_rate; + + struct atm_dev *dev; +}; + +struct connection { + struct atm_vcc *vcc; + + volatile struct tx_descriptor + *tx_desc; + unsigned int tx_desc_pos; + struct sk_buff **tx_skb; + + unsigned int aal5_vcc_crc_err; /* number of packets with CRC error */ + unsigned int aal5_vcc_oversize_sdu; /* number of packets with oversize error */ + + unsigned int port; +}; + +struct atm_priv_data { + unsigned long conn_table; + struct connection conn[MAX_PVC_NUMBER]; + + volatile struct rx_descriptor + *aal_desc; + unsigned int aal_desc_pos; + + volatile struct rx_descriptor + *oam_desc; + unsigned char *oam_buf; + unsigned int oam_desc_pos; + + struct port port[ATM_PORT_NUMBER]; + + unsigned int wrx_pdu; /* successfully received AAL5 packet */ + unsigned int wrx_drop_pdu; /* AAL5 packet dropped by driver on RX */ + unsigned int wtx_pdu; /* successfully tranmitted AAL5 packet */ + unsigned int wtx_err_pdu; /* error AAL5 packet */ + unsigned int wtx_drop_pdu; /* AAL5 packet dropped by driver on TX */ + + ppe_u64_t wrx_total_byte; + ppe_u64_t wtx_total_byte; + unsigned int prev_wrx_total_byte; + unsigned int prev_wtx_total_byte; + + void *aal_desc_base; + void *oam_desc_base; + void *oam_buf_base; + void *tx_desc_base; + void *tx_skb_base; +}; + + + +/* + * #################################### + * Declaration + * #################################### + */ + +extern unsigned int ifx_atm_dbg_enable; + +extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor); + +extern void ifx_atm_init_chip(void); +extern void ifx_atm_uninit_chip(void); + +extern int ifx_pp32_start(int pp32); +extern void ifx_pp32_stop(int pp32); + +extern void ifx_reset_ppe(void); + + + +#endif // IFXMIPS_ATM_CORE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_danube.c b/package/system/ltq-dsl/src/ifxmips_atm_danube.c new file mode 100644 index 0000000000..64698b8792 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_danube.c @@ -0,0 +1,326 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_danube.c +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver common source file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <linux/clk.h> +#include <asm/delay.h> + +/* + * Chip Specific Head File + */ +#include <lantiq_soc.h> +#include "ifxmips_compat.h" +#include "ifxmips_atm_core.h" +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + #include "ifxmips_atm_fw_danube_retx.h" +#else + #include "ifxmips_atm_fw_danube.h" +#endif + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * EMA Settings + */ +#define EMA_CMD_BUF_LEN 0x0040 +#define EMA_CMD_BASE_ADDR (0x00001580 << 2) +#define EMA_DATA_BUF_LEN 0x0100 +#define EMA_DATA_BASE_ADDR (0x00001900 << 2) +#define EMA_WRITE_BURST 0x2 +#define EMA_READ_BURST 0x2 + + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Hardware Init/Uninit Functions + */ +static inline void init_pmu(void); +static inline void uninit_pmu(void); +static inline void reset_ppe(void); +static inline void init_ema(void); +static inline void init_mailbox(void); +static inline void init_atm_tc(void); +static inline void clear_share_buffer(void); + + + +/* + * #################################### + * Local Variable + * #################################### + */ + + + +/* + * #################################### + * Local Function + * #################################### + */ + +static inline void init_pmu(void) +{ + //*(unsigned long *)0xBF10201C &= ~((1 << 15) | (1 << 13) | (1 << 9)); + //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE); +/* PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TC_PMU_SETUP(IFX_PMU_ENABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE);*/ + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_enable(clk); +} + +static inline void uninit_pmu(void) +{ +/* PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TC_PMU_SETUP(IFX_PMU_DISABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE);*/ + //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE); + struct clk *clk = clk_get_sys("ltq_dsl", NULL); + clk_disable(clk); +} + +static inline void reset_ppe(void) +{ +#if 0 //def MODULE + unsigned int etop_cfg; + unsigned int etop_mdio_cfg; + unsigned int etop_ig_plen_ctrl; + unsigned int enet_mac_cfg; + + etop_cfg = *IFX_PP32_ETOP_CFG; + etop_mdio_cfg = *IFX_PP32_ETOP_MDIO_CFG; + etop_ig_plen_ctrl = *IFX_PP32_ETOP_IG_PLEN_CTRL; + enet_mac_cfg = *IFX_PP32_ENET_MAC_CFG; + + *IFX_PP32_ETOP_CFG &= ~0x03C0; + + // reset PPE + ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM); + + *IFX_PP32_ETOP_MDIO_CFG = etop_mdio_cfg; + *IFX_PP32_ETOP_IG_PLEN_CTRL = etop_ig_plen_ctrl; + *IFX_PP32_ENET_MAC_CFG = enet_mac_cfg; + *IFX_PP32_ETOP_CFG = etop_cfg; +#endif +} + +static inline void init_ema(void) +{ + IFX_REG_W32((EMA_CMD_BUF_LEN << 16) | (EMA_CMD_BASE_ADDR >> 2), EMA_CMDCFG); + IFX_REG_W32((EMA_DATA_BUF_LEN << 16) | (EMA_DATA_BASE_ADDR >> 2), EMA_DATACFG); + IFX_REG_W32(0x000000FF, EMA_IER); + IFX_REG_W32(EMA_READ_BURST | (EMA_WRITE_BURST << 2), EMA_CFG); +} + +static inline void init_mailbox(void) +{ + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU1_IER); + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU3_IER); +} + +static inline void init_atm_tc(void) +{ + IFX_REG_W32(0x0000, DREG_AT_CTRL); + IFX_REG_W32(0x0000, DREG_AR_CTRL); + IFX_REG_W32(0x0, DREG_AT_IDLE0); + IFX_REG_W32(0x0, DREG_AT_IDLE1); + IFX_REG_W32(0x0, DREG_AR_IDLE0); + IFX_REG_W32(0x0, DREG_AR_IDLE1); + IFX_REG_W32(0x40, RFBI_CFG); + IFX_REG_W32(0x1600, SFSM_DBA0); + IFX_REG_W32(0x1718, SFSM_DBA1); + IFX_REG_W32(0x1830, SFSM_CBA0); + IFX_REG_W32(0x1844, SFSM_CBA1); + IFX_REG_W32(0x14014, SFSM_CFG0); + IFX_REG_W32(0x14014, SFSM_CFG1); + IFX_REG_W32(0x1858, FFSM_DBA0); + IFX_REG_W32(0x18AC, FFSM_DBA1); + IFX_REG_W32(0x10006, FFSM_CFG0); + IFX_REG_W32(0x10006, FFSM_CFG1); + IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC0); + IFX_REG_W32(0x00000001, FFSM_IDLE_HEAD_BC1); +} + +static inline void clear_share_buffer(void) +{ + volatile u32 *p = SB_RAM0_ADDR(0); + unsigned int i; + + for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ ) + IFX_REG_W32(0, p++); +} + +/* + * Description: + * Download PPE firmware binary code. + * Input: + * src --- u32 *, binary code buffer + * dword_len --- unsigned int, binary code length in DWORD (32-bit) + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +static inline int pp32_download_code(u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len) +{ + volatile u32 *dest; + + if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0 + || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 ) + return IFX_ERROR; + + if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) ) + IFX_REG_W32(0x00, CDM_CFG); + else + IFX_REG_W32(0x04, CDM_CFG); + + /* copy code */ + dest = CDM_CODE_MEMORY(0, 0); + while ( code_dword_len-- > 0 ) + IFX_REG_W32(*code_src++, dest++); + + /* copy data */ + dest = CDM_DATA_MEMORY(0, 0); + while ( data_dword_len-- > 0 ) + IFX_REG_W32(*data_src++, dest++); + + return IFX_SUCCESS; +} + + + +/* + * #################################### + * Global Function + * #################################### + */ + +extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor) +{ + ASSERT(major != NULL, "pointer is NULL"); + ASSERT(minor != NULL, "pointer is NULL"); + +#if (defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX) || defined(VER_IN_FIRMWARE) + *major = FW_VER_ID->major; + *minor = FW_VER_ID->minor; +#else + *major = ATM_FW_VER_MAJOR; + *minor = ATM_FW_VER_MINOR; +#endif +} + +void ifx_atm_init_chip(void) +{ + init_pmu(); + + reset_ppe(); + + init_ema(); + + init_mailbox(); + + init_atm_tc(); + + clear_share_buffer(); +} + +void ifx_atm_uninit_chip(void) +{ + uninit_pmu(); +} + +/* + * Description: + * Initialize and start up PP32. + * Input: + * none + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +int ifx_pp32_start(int pp32) +{ + int ret; + + /* download firmware */ + ret = pp32_download_code(firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data)); + if ( ret != IFX_SUCCESS ) + return ret; + + /* run PP32 */ + IFX_REG_W32(DBG_CTRL_START_SET(1), PP32_DBG_CTRL); + + /* idle for a while to let PP32 init itself */ + udelay(10); + + return IFX_SUCCESS; +} + +/* + * Description: + * Halt PP32. + * Input: + * none + * Output: + * none + */ +void ifx_pp32_stop(int pp32) +{ + /* halt PP32 */ + IFX_REG_W32(DBG_CTRL_STOP_SET(1), PP32_DBG_CTRL); +} diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h new file mode 100644 index 0000000000..4daef9fd8c --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_amazon_se.h @@ -0,0 +1,3335 @@ +#ifndef IFXMIPS_ATM_FW_AMAZON_SE_H +#define IFXMIPS_ATM_FW_AMAZON_SE_H + + +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_amazon_se.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PP32 Firmware) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + +#define ATM_FW_VER_MAJOR 0 +#define ATM_FW_VER_MINOR 1 + + +static unsigned int firmware_binary_code[] = { +0x80000ac0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x8000ffe0, +0x00000000, +0x00000000, +0x00000000, +0xc1000002, +0xd90c00f8, +0xc2000002, +0xda0800f9, +0x80004d48, +0xc2000000, +0xda0800f9, +0x800043b8, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80004370, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80005550, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80004270, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0xc0400000, +0xc0004840, +0xc88400f8, +0x80004a08, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0xc0400002, +0xc0004840, +0xc88400f8, +0x80004988, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0xc3c00004, +0xdbc800f9, +0xc10c0002, +0xd90c00f8, +0x8000fee0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0xc10e0002, +0xd90c00f8, +0xc0004808, +0xc84000f8, +0x800049b8, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003ff0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003f70, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003ef0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003e70, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003df0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003d70, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003cf0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003c70, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003bf0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003b70, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x80003af0, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0xc0000000, +0xc1260002, +0xd90c00f8, +0xc2801af0, +0xc201757c, +0xc2417dde, +0x00000000, +0x00000000, +0xce2800f8, +0x00000000, +0x5aa80002, +0x00000000, +0xce6800f8, +0x00000000, +0x80003a00, +0x00000000, +0x00000000, +0xc3e1fffe, +0x597dffee, +0x593dfe14, +0x90000ae1, +0x00000000, +0x00000000, +0x00000000, +0x90cc0a89, +0x00000000, +0x00000000, +0x00000000, +0xc3c00000, +0xdbc800f9, +0xc1400008, +0xc1900000, +0x71588000, +0x14100100, +0xc140000a, +0xc1900002, +0x71588000, +0x14100100, +0xc140000c, +0xc1900004, +0x71588000, +0x14100100, +0xc1400004, +0xc1900006, +0x71588000, +0x14100100, +0xc1400006, +0xc1900008, +0x71588000, +0x14100100, +0xc140000e, +0xc190000a, +0x71588000, +0x14100100, +0xc1400000, +0xc190000c, +0x71588000, +0x14100100, +0xc1400002, +0xc190000e, +0x71588000, +0x14100100, +0xc0400000, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0xc11c0002, +0xc000082c, +0xcd05ce00, +0xc0400002, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0xc11c0002, +0xc000082c, +0xcd05ce00, +0xc0000824, +0x00000000, +0xcbc000f9, +0xcb8000f9, +0xcb4000f9, +0xcb0000f8, +0xc0004878, +0x5bfc4000, +0xcfc000f9, +0x5bb84000, +0xcf8000f9, +0x5b744000, +0xcf4000f9, +0x5b304000, +0xcf0000f8, +0xc0000a10, +0x00000000, +0xcbc000f9, +0xcb8000f8, +0xc0004874, +0x5bfc4000, +0xcfc000f9, +0x5bb84000, +0xcf8000f8, +0xc30001fe, +0xc000140a, +0xcf0000f8, +0xc3000000, +0x7f018000, +0xc000042e, +0xcf0000f8, +0xc000040e, +0xcf0000f8, +0xc3c1fffe, +0xc000490e, +0xcfc00078, +0xc000492c, +0xcfc00078, +0xc0004924, +0xcfc00038, +0xc0004912, +0xcfc00038, +0xc0004966, +0xcfc00038, +0xc0004968, +0xcfc00078, +0xc000496a, +0xcfc00078, +0xc3c00000, +0xc2800020, +0xc3000000, +0x7f018000, +0x6ff88000, +0x6fd44000, +0x4395c000, +0x5bb84a00, +0x5838000a, +0xcf0000f8, +0x5bfc0002, +0xb7e8ffc8, +0x00000000, +0xc3c00000, +0xc2800010, +0x6ff86000, +0x47bdc000, +0x5bb84c80, +0xc3400000, +0x58380004, +0xcb420078, +0x00000000, +0x58380008, +0xcf400078, +0x5bfc0002, +0xb7e8ffb0, +0x00000000, +0xc3c00000, +0xc2800020, +0xc348001e, +0xc3000000, +0x7f018000, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x58380008, +0xcf408418, +0x5838000a, +0xcf0000f8, +0x5bfc0002, +0xb7e8ffb0, +0x00000000, +0x00000000, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x80000530, +0x00000000, +0x80002130, +0x00000000, +0x8000ffe0, +0xc0004958, +0xc84000f8, +0x00000000, +0xc3c00002, +0x787c2000, +0xcc4000f8, +0xc0004848, +0xcb8400f8, +0xc000495c, +0xcac400f8, +0xc0004844, +0xc88400f8, +0x47ad0000, +0x8400ff82, +0xc000487c, +0xc80400f8, +0x00000000, +0x00000000, +0x40080000, +0xca0000f8, +0xc0001624, +0xcb0400f8, +0xa63c007a, +0x00000000, +0x00000000, +0xa71eff22, +0x00000000, +0xc0000824, +0xca8400f8, +0x6ca08000, +0x6ca42000, +0x46250000, +0x42290000, +0xc35e0002, +0xc6340060, +0xc0001624, +0xcf440078, +0xc2000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc0004844, +0xc88400f8, +0xc000082c, +0xca040038, +0x00000000, +0x00000000, +0x58880002, +0xb6080018, +0x00000000, +0xc0800000, +0xc0004844, +0xcc840038, +0x5aec0002, +0xc000495c, +0xcec400f8, +0x5e6c0006, +0x84000060, +0xc0004848, +0xcb8400f8, +0xc0000838, +0xc2500002, +0xce450800, +0x5fb80002, +0xc0004848, +0xcf8400f8, +0x5eec0002, +0xc000495c, +0xcec400f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x8000fd98, +0xc000495a, +0xc84000f8, +0x00000000, +0xc3c00002, +0x787c2000, +0xcc4000f8, +0xc0004960, +0xcac400f8, +0x00000000, +0x00000000, +0x5eec0000, +0x8400010a, +0x00000000, +0xb6fc0050, +0xc0001600, +0xca0400f8, +0x00000000, +0x00000000, +0xa61e00d2, +0x6fe90000, +0xc0000a28, +0xce850800, +0xc2c00000, +0xc2800004, +0xb6e800a0, +0xc0001604, +0xca8400f8, +0xc0004960, +0xcec400f8, +0xa69efcc2, +0x00000000, +0x6fe90000, +0xc0000a28, +0xce850800, +0xc2c00002, +0xc0001600, +0xca0400f8, +0x00000000, +0x00000000, +0xa61e002a, +0x6fe90000, +0xc0000a28, +0xce850800, +0xc2c00000, +0xc0001604, +0xca8400f8, +0xc0004960, +0xcec400f8, +0xa69efc2a, +0xc2400000, +0xc0000a14, +0xca440028, +0x00000000, +0x00000000, +0x466d2000, +0xa4400020, +0xc2800000, +0xdfeb0029, +0x80000010, +0xdfea0029, +0xb668fba2, +0x00000000, +0xc00048a0, +0xcb0400f8, +0xc0000a10, +0xca8400f8, +0x6f208000, +0x6f242000, +0x46250000, +0x42a10000, +0xc2400000, +0xc0000a14, +0xca440028, +0xc35e0002, +0xc6340060, +0xc0001604, +0xcf440078, +0x5b300002, +0xb6700018, +0x5aec0002, +0xc3000000, +0xc00048a0, +0xcf0400f8, +0xc0004960, +0xcec400f8, +0x8000fad8, +0xc0004918, +0xd28000f8, +0xc2000000, +0xdf600038, +0x5e600080, +0x84000272, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000480a, +0xca0000f8, +0xc0004912, +0xca4000f8, +0xc0004924, +0xca8000f8, +0xc0004966, +0xcac000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x76250000, +0x76290000, +0x762d0000, +0x840001ca, +0xc0004918, +0xca4000f8, +0xc28001fe, +0x76290000, +0x5a640002, +0x6a254010, +0x5ee80000, +0x8400001a, +0x6aa54000, +0x80000010, +0xc62800f8, +0x62818008, +0xc0004918, +0xcf0000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc0004966, +0xca4000f8, +0xc2000002, +0x6a310000, +0x7e010000, +0x76612000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x6f346000, +0x4771a000, +0x5b744c80, +0xc2800000, +0x58340006, +0xca800078, +0xc2c00000, +0x58340000, +0xcac000d8, +0xc2400000, +0x5834000a, +0xca420078, +0x6ea82000, +0x42e9e000, +0x6f2ca000, +0x42e56000, +0x5aec1400, +0xc3990040, +0xc7381c18, +0xc6f80060, +0x99005f50, +0xdb9800f8, +0xdbd800f9, +0x00000000, +0xdea000f8, +0x46310000, +0x8400fd80, +0xc0004958, +0xc84000f8, +0x00000000, +0xc3c00002, +0x787c2000, +0xcc4000f8, +0xc0004848, +0xcb8400f8, +0xc0004844, +0xc88400f8, +0x5fb80000, +0x8400f7f2, +0xc0001a1c, +0xca0000f8, +0xc2400002, +0x6a452000, +0x76250000, +0x8400f7c2, +0xc000487c, +0xc80400f8, +0x00000000, +0x00000000, +0x40080000, +0xca0000f8, +0xc42400f8, +0x00000000, +0xa63c17da, +0x00000000, +0xc0004878, +0xc80400f8, +0x6c908000, +0x45088000, +0x45088000, +0x40100000, +0xca0000f8, +0xc42400f8, +0x00000000, +0xc0004934, +0xce0000f8, +0xc2800002, +0xc4681c08, +0xc62821d0, +0xc2600010, +0x5a652440, +0xc0004800, +0xcb4000f8, +0xc2200400, +0x5a202400, +0xc7601040, +0xc0001220, +0xce8000f8, +0xc0001200, +0xce4000f8, +0xc0001202, +0xce0000f8, +0xc0001240, +0xcb4000f8, +0x00000000, +0x00000000, +0xa754ffe0, +0xc2000000, +0xc7600040, +0xa7520042, +0x00000000, +0x00000000, +0x990066c8, +0xc0004822, +0xc94000f8, +0xc1800002, +0x80001680, +0x58206480, +0xc2000000, +0xca000018, +0xc2400000, +0xca414000, +0xc2800000, +0xca812000, +0xc2c00000, +0xcac20018, +0xc0004938, +0xce0000f8, +0xc0004920, +0xce4000f8, +0xc0004916, +0xce8000f8, +0xc0004922, +0xcec000f8, +0xa6400540, +0x00000000, +0xc0004938, +0xcbc000f8, +0x00000000, +0xc3800000, +0x6ff48000, +0x6fd44000, +0x4355a000, +0x5b744a00, +0x58340000, +0xcb802010, +0x00000000, +0xc2000000, +0x6fb46000, +0x4779a000, +0x5b744c80, +0x5834000c, +0xca000020, +0xc000491a, +0xcf8000f8, +0x5e200000, +0x8400046a, +0xc2000000, +0xdf610048, +0x5e6001e8, +0x8800ffe8, +0xc2000002, +0xc2400466, +0xc2a00000, +0x5aa80000, +0xc0001006, +0xce0000f8, +0xc0001008, +0xce4000f8, +0xc000100a, +0xce8000f8, +0x99005990, +0xc1a0fffe, +0xc0000824, +0xc9840060, +0xc0004934, +0xca4000f8, +0xc2000000, +0xc2800002, +0x990059d0, +0xda9800f8, +0xc61400f8, +0xc65800f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0x99005ab8, +0xc000491a, +0xc94000f8, +0x00000000, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0xc0004922, +0xca001118, +0xc3c00000, +0xc3800000, +0xc0004930, +0xce023118, +0xc0004932, +0xcbc000d8, +0xc2800000, +0xc000491e, +0xcfc000f8, +0xc0004862, +0xca800060, +0xc3a0001a, +0x5bb94000, +0xc6b80060, +0xc000491c, +0xcf8000f8, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0x00000000, +0x00000000, +0x00000000, +0xa8e2ffe8, +0xc2000000, +0xc1220002, +0xd90c00f8, +0xdf600038, +0x5e600080, +0x8400fff2, +0xc000491c, +0xca0000f8, +0xc000491e, +0xca4000f8, +0x00000000, +0x00000000, +0x99005f50, +0xda1800f8, +0xda5800f9, +0x00000000, +0xc2000000, +0xdf610048, +0x5e6001fe, +0x8800ffe8, +0xc0004916, +0xca8000f8, +0xc2c00000, +0xdfec0048, +0xc2400000, +0x466d2000, +0x8400004a, +0x5ea80000, +0x8400003a, +0xc2600002, +0x990066c8, +0xc000482e, +0xc94000f8, +0xc1800002, +0x80000030, +0xc2600000, +0x990066c8, +0xc000482c, +0xc94000f8, +0xc1800002, +0xc2000068, +0xc6240078, +0xc0004930, +0xce400080, +0xc000491a, +0xc98000f8, +0xc0004862, +0xc94000f8, +0x6d9c6000, +0x45d8e000, +0x59dc4c80, +0x99005db0, +0xd95800f8, +0xd99800f9, +0xd9d400f8, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0xc2000000, +0xdf600038, +0x5e600080, +0x8400ffea, +0x00000000, +0xc000491c, +0xca0000f8, +0xc000491e, +0xca4000f8, +0x00000000, +0x00000000, +0x99005f50, +0xda1800f8, +0xda5800f9, +0x00000000, +0x800010e8, +0x00000000, +0x990066c8, +0xc000482a, +0xc94000f8, +0xc1800002, +0x800010b8, +0xc0004938, +0xcbc000f8, +0x00000000, +0x00000000, +0x6ff88000, +0x6fd44000, +0x4395c000, +0x5bb84a00, +0x58380008, +0xca0000f8, +0x00000000, +0x00000000, +0xa6000382, +0x00000000, +0xc0004938, +0xcbc000f8, +0xc3000000, +0x00000000, +0x6ff88000, +0x6fd44000, +0x4395c000, +0x5bb84a00, +0x58380000, +0xcb002010, +0xc2000000, +0x58380008, +0xca020078, +0x5838000c, +0xcac000f8, +0x5838000e, +0xca4000f8, +0xc000491a, +0xcf0000f8, +0xc0004930, +0xcec000f8, +0xc000493c, +0xce0000f8, +0xc0004932, +0xce4000f8, +0x5e200000, +0x84000120, +0xc2800000, +0xa6fe00ba, +0x6f206000, +0x46310000, +0x5a204c80, +0x5820000c, +0xca800020, +0x00000000, +0x00000000, +0x5ea80000, +0x840001f2, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0x99005ab8, +0xc000491a, +0xc94000f8, +0x00000000, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0xc0004930, +0xcac000f8, +0xc0004932, +0xca4000f8, +0xc7ec1118, +0xc0004930, +0xcec000f8, +0x5838000c, +0xcec000f8, +0x58000002, +0xce4000f8, +0xc0004934, +0xca0000f8, +0xc2400002, +0x6e642000, +0x6e642000, +0x76612000, +0x8400002a, +0xc2400002, +0x6e684000, +0x58380008, +0xce804200, +0xa6000020, +0x6e682000, +0x58380008, +0xce802100, +0xc2400002, +0x6e642000, +0x76612000, +0x840000ea, +0x58380008, +0xca0000f8, +0xc2800000, +0xc2400000, +0xa60200c0, +0xdba800f8, +0x6f386000, +0x47b1c000, +0x5bb84c80, +0x58380004, +0xca400078, +0x58380002, +0xca800078, +0x00000000, +0xdeb800f8, +0x46a54000, +0x88000060, +0x00000000, +0xc0004824, +0xca0000f8, +0xc2400002, +0x6e640000, +0x5a200002, +0xce0000f8, +0x58380008, +0xce400000, +0x80000018, +0x00000000, +0x80000048, +0xc0004934, +0xca0000f8, +0x00000000, +0x00000000, +0xa6020c6a, +0x00000000, +0x00000000, +0x80000c98, +0xc2800000, +0xc2000200, +0xc240001a, +0xdf690048, +0x46294000, +0x46a54000, +0x8800ffd2, +0xc2000006, +0xc2600982, +0x5a643b6e, +0x5838000a, +0xca8000f8, +0xc0001006, +0xce0000f8, +0xc0001008, +0xce4000f8, +0xc000100a, +0xce8000f8, +0x99005990, +0xc1a0fffe, +0xc0000824, +0xc9840060, +0xc2000000, +0xc0004930, +0xca02e008, +0x58380026, +0xca4000f8, +0x00000000, +0xc2800000, +0x990059d0, +0xda9800f8, +0xc61400f8, +0xc65800f8, +0xc0004934, +0xca0000f8, +0x00000000, +0x00000000, +0xa6020022, +0x00000000, +0x00000000, +0x80000318, +0xc0004938, +0xcbc000f8, +0xc0004878, +0xc80400f8, +0x6c908000, +0x45088000, +0x45088000, +0x40100000, +0xca0000f8, +0xc42400f8, +0x00000000, +0x58240018, +0xca0000f8, +0x6ff88000, +0x6fd44000, +0x4395c000, +0x5bb84a00, +0xc3000000, +0xc3400002, +0xc2c00000, +0xc62c0078, +0xc6270038, +0xc0004940, +0xce400038, +0xc6260038, +0xc0004942, +0xce400038, +0xc000493c, +0xca0000f8, +0x5eec0000, +0x8400018a, +0x5a6c0010, +0x46254000, +0x88000190, +0x5a600052, +0x46e54000, +0x88000178, +0x58380006, +0xca8000f8, +0xc0004940, +0xca0000f8, +0xc2400000, +0xc6a70038, +0x7e412000, +0x76612000, +0xc2000000, +0xc6a10038, +0x46250000, +0x84000138, +0xc0004942, +0xca0000f8, +0xc2400000, +0xc6a60038, +0x7e412000, +0x76612000, +0xc2000000, +0xc6a00038, +0x58380002, +0xca8000f8, +0x46250000, +0x840000e8, +0xc2400000, +0xc6a60078, +0x466d0000, +0x880000da, +0xc2400000, +0xc6a40078, +0x58380008, +0xca8000f8, +0x46e50000, +0x880000ba, +0x00000000, +0xa6820018, +0x00000000, +0xc7700b00, +0xa6840098, +0x00000000, +0xc7700a00, +0x80000080, +0xc7700200, +0xc000493c, +0xcac000f8, +0x80000060, +0xc7700300, +0xc000493c, +0xcac000f8, +0x80000040, +0xc7700900, +0x80000030, +0xc7700800, +0x80000020, +0xc7700700, +0x80000010, +0xc7700500, +0xc0004944, +0xcf0000f8, +0xc000493e, +0xcec000f8, +0xc0004938, +0xca4000f8, +0xc000493c, +0xcb8000f8, +0xc000493e, +0xcb4000f8, +0xc3000000, +0x6e608000, +0x6e544000, +0x42150000, +0x5a204a00, +0x5aa00008, +0x58200004, +0xcb000078, +0xc0004934, +0xca0000f8, +0xc2400000, +0xc0004930, +0xca42e008, +0xc3c00018, +0xa6020098, +0x00000000, +0x43656000, +0x47ad0000, +0x88000050, +0x46f96000, +0x6ee04010, +0x5be00004, +0xc2000000, +0xc6e00008, +0x5e200000, +0x84000042, +0x5bfc0002, +0x80000030, +0xc3c00004, +0x5a2c0008, +0x47a10000, +0x88000012, +0x5fb80008, +0x6fe04000, +0x42390000, +0x47212000, +0x88000068, +0xc2400000, +0xc0004930, +0xca42e008, +0xc2060002, +0xc68000f8, +0xce006300, +0x6fe04000, +0x4721c000, +0x5f700010, +0x4765a000, +0xc2000000, +0xc6340008, +0xc25a000a, +0xc000491a, +0xca401c18, +0xc2800000, +0xc0004932, +0xca8000d8, +0xc0004862, +0xca400060, +0x6fa04010, +0x42290000, +0xc000491e, +0xce0000f8, +0xc7e41048, +0xc000491c, +0xce4000f8, +0x6fe04000, +0x43a1c000, +0xc000493c, +0xcf8000f8, +0xc000493e, +0xcf4000f8, +0xc000493a, +0xcfc000f8, +0x80000008, +0x00000000, +0x00000000, +0x00000000, +0xc2000000, +0xdce000f8, +0xa622ffd8, +0xc1220002, +0xd90c00f8, +0xc0004938, +0xcbc000f8, +0xc0004944, +0xcb4000f8, +0xc0004862, +0xcb0000f8, +0xc0004934, +0xca0000f8, +0x6ff88000, +0x6fd44000, +0x4395c000, +0x5bb84a00, +0xa6020268, +0xc2400000, +0x58380008, +0xca406000, +0xdfe800f8, +0xc2218e08, +0x5a21baf6, +0x46a14000, +0x84000022, +0xc2080002, +0x7361a000, +0x80000058, +0x5e640000, +0x84000022, +0xc20c0002, +0x7361a000, +0x80000030, +0xc2000000, +0xc760e710, +0xc7604218, +0x5e200000, +0x84000272, +0xc2200002, +0xc0004930, +0xce021000, +0x990066c8, +0xc0004828, +0xc94000f8, +0xc1800002, +0x58380000, +0xca0000f8, +0x00000000, +0x00000000, +0xa6000132, +0xc0004940, +0xca8000f8, +0xc0004942, +0xca4000f8, +0xc7600078, +0xc6a01838, +0xc6601038, +0xc000493a, +0xca4000f8, +0xc0004934, +0xca8000f8, +0xc0005600, +0x40300000, +0x40240000, +0x5c000004, +0x5ec05800, +0x88000012, +0x5c000200, +0xce0000f8, +0x58000002, +0x5ec05800, +0x88000012, +0x5c000200, +0xce8000f8, +0xc000493e, +0xca0000f8, +0xc2400000, +0x5838000c, +0xce4000f8, +0x990066c8, +0xc0004830, +0xc94000f8, +0xc61800f8, +0xc0004930, +0xc6100078, +0xcd000078, +0x800000a8, +0xc2400002, +0x58380008, +0xce400000, +0xc0004944, +0xcf4000f8, +0x80000278, +0xc000493c, +0xca4000f8, +0xdfe800f8, +0x5a300018, +0xc0005600, +0x40200000, +0xca0000f8, +0x58380008, +0xc6501078, +0xcd021078, +0x5838000a, +0xce8000f8, +0x58380026, +0xce0000f8, +0xc0004944, +0xcf4000f8, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0x80000038, +0x00000000, +0x990066c8, +0xc0004826, +0xc94000f8, +0xc1800002, +0x8000fdd8, +0xc2000000, +0xc2400200, +0xdf600038, +0xb624ffea, +0xc000491c, +0xca4000f8, +0xc000491e, +0xca8000f8, +0x99005f50, +0xda5800f8, +0xda9800f9, +0x00000000, +0xc0004934, +0xca0000f8, +0x00000000, +0xc2800000, +0xa6020160, +0xc2400004, +0xc2000200, +0xdf690048, +0x46294000, +0x46a54000, +0x8800ffda, +0x00000000, +0xc000491a, +0xc98000f8, +0xc0004862, +0xc94000f8, +0x6d9c6000, +0x45d8e000, +0x59dc4c80, +0x99005db0, +0xd95800f8, +0xd99800f9, +0xd9d400f8, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0xc2000000, +0xc2400200, +0xdf600038, +0xb624ffea, +0xc000491c, +0xca4000f8, +0xc000491e, +0xca8000f8, +0x99005f50, +0xda5800f8, +0xda9800f9, +0x00000000, +0x58380008, +0xca4000f8, +0xc2000000, +0xce000018, +0xc2a1fffe, +0x5aa9fffe, +0xce021078, +0x5838000a, +0xce8000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc0000838, +0xc2500002, +0xce450800, +0xc0004848, +0xcb8400f8, +0xc2000000, +0xc000082c, +0xca040028, +0x5fb80002, +0xc0004848, +0xcf8400f8, +0x58880002, +0xb6080018, +0x00000000, +0xc0800000, +0xc0004844, +0xcc8400f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x8000ded8, +0xc2000000, +0xdf600038, +0x5e200080, +0x8400026a, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000480c, +0xca0000f8, +0xc0004910, +0xca4000f8, +0xc000492c, +0xca8000f8, +0xc0004968, +0xcac000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x76250000, +0x76290000, +0x76e16000, +0x840001c2, +0xc0004926, +0xca4000f8, +0xc201fffe, +0x76e16000, +0x5a640002, +0x6ae50010, +0x5f200000, +0x8400001a, +0x6a250000, +0x80000010, +0xc6e000f8, +0x62014008, +0xc0004926, +0xce8000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc0004968, +0xca4000f8, +0xc2000002, +0x6a290000, +0x7e010000, +0x76612000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x6eb4a000, +0x6e944000, +0x4755a000, +0x4769a000, +0x5b745e00, +0x58340002, +0xc2000000, +0xca0000d8, +0x5834002e, +0xc2400000, +0xca400078, +0x6eb0a000, +0x6ebc4000, +0x473d8000, +0x47298000, +0x5b301e2e, +0x5b300004, +0x6e642000, +0x4225e000, +0xc39a8024, +0xc7380060, +0xc6b81c18, +0x99005f50, +0xdb9800f8, +0xdbd800f9, +0x00000000, +0xc2000000, +0xdf600038, +0x5e200080, +0x840002a2, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000490e, +0xca0000f8, +0xc000492a, +0xca4000f8, +0xc000496a, +0xcb0000f8, +0xc0004956, +0xcac000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x77218000, +0x77258000, +0x84000202, +0xc201fffe, +0x77218000, +0x5aec0002, +0x6b2d0010, +0x5ea00000, +0x8400001a, +0x6a2d0000, +0x80000010, +0xc72000f8, +0x62016008, +0xc0004956, +0xcec000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000496a, +0xca4000f8, +0xc2000002, +0x6a2d0000, +0x7e010000, +0x76612000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x6ef4a000, +0x6ed44000, +0x4755a000, +0x476da000, +0x5b745e00, +0x5834000e, +0xc2000000, +0xca0000d8, +0x58340008, +0xc2400000, +0xca420078, +0x5834000c, +0xc2800000, +0xca832010, +0x6e644010, +0x42250000, +0x4229e000, +0xc39a8008, +0x58340008, +0xcb809018, +0x58340008, +0xc2800000, +0xca810010, +0x6ee0a000, +0x6ee44000, +0x46250000, +0x462d0000, +0x5a200008, +0x5a201e08, +0x42290000, +0xc6380060, +0xc6f81c18, +0x99005f50, +0xdb9800f8, +0xdbd800f9, +0x00000000, +0xc000495a, +0xc84000f8, +0x00000000, +0xc3c00002, +0x787c2000, +0xcc4000f8, +0xc0001a1c, +0xca0000f8, +0xc2400008, +0x6a452000, +0x76250000, +0x8400d932, +0xc0000a28, +0xc3800000, +0xcb840028, +0xc0000a14, +0xc3400000, +0xcb440028, +0xc0004880, +0xcb0400f8, +0xb7b4d8ea, +0x58041802, +0xcac000f8, +0xa7000038, +0x00000000, +0x00000000, +0xa6c8d8b8, +0xc2800000, +0xc6e80018, +0x80000048, +0xc2800000, +0xc7282018, +0xc000490e, +0xca4000f8, +0x6be9e000, +0x00000000, +0x767d2000, +0x8400d860, +0x6ea0a000, +0x6e944000, +0x46150000, +0x46290000, +0x5a205e00, +0x5820000c, +0xca0000f8, +0xc0004946, +0xce8000f8, +0xa6220368, +0x00000000, +0xc2200060, +0xc0004948, +0xce000008, +0xce021038, +0xc240000a, +0xc000494a, +0xce4000f8, +0xc2b60002, +0xc0004964, +0xce837b00, +0x99006220, +0xc00048a0, +0xc88400f8, +0x00000000, +0xc0004946, +0xcbc000f8, +0x00000000, +0x00000000, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x99005fe0, +0xdbd800f8, +0xdb9800f9, +0x00000000, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0xc000491c, +0x990061d8, +0xc94000f9, +0xc98000f8, +0x00000000, +0x99005f50, +0xd95800f8, +0xd99800f9, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0x99005c18, +0xdbd800f8, +0xdb9800f9, +0xc7d800f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x58380010, +0xca0000f8, +0xc0004874, +0xc80400f8, +0x6c908000, +0x45088000, +0x45088000, +0x40100000, +0xca4000f8, +0xc43400f8, +0x00000000, +0xc74000f8, +0xce0000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000490e, +0xca4000f8, +0xc2800002, +0x6abd4000, +0x72692000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x990066c8, +0xc0004836, +0xc94000f8, +0xc1800002, +0x00000000, +0x00000000, +0x00000000, +0xa8e2ffe8, +0x00000000, +0xc1220002, +0xd90c00f8, +0xc2000000, +0xc0000a14, +0xca040028, +0xc0000a28, +0xc2500002, +0xce450800, +0x58880002, +0xb6080018, +0xc00048a0, +0xc0800000, +0xcc8400f8, +0x8000d4b0, +0xc0004946, +0xcbc000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000490e, +0xca4000f8, +0xc2800002, +0x6abd4000, +0x72692000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x58380008, +0xca0000f8, +0x5838000c, +0xca4000f8, +0xc3400000, +0xc6340000, +0xc000494e, +0xcf4000f8, +0xc2800000, +0xc62a0078, +0xc3000000, +0xc6308018, +0x6f304000, +0x43298000, +0xc000493c, +0xcf0000f8, +0xc2c00000, +0xc66c0078, +0xc0004950, +0xcec000f8, +0xc2800000, +0xc66ae020, +0xc0004954, +0xce8000f8, +0x5f740000, +0x840001a0, +0x5e300028, +0x46e12000, +0x8400016a, +0x46e12000, +0x88000132, +0x5e300018, +0x46e12000, +0x8800002a, +0x46e12000, +0x84000042, +0x00000000, +0x800000c0, +0x00000000, +0x99006360, +0xdbd800f8, +0xdb9800f9, +0xc78000f8, +0xc3400002, +0xc000494e, +0xcf4000f8, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc000490e, +0xca4000f8, +0xc2800002, +0x6abd4000, +0x7e814000, +0x76692000, +0xce4000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0xc2200060, +0xc0004948, +0xce021038, +0xc2000000, +0xc000494c, +0xce0000f8, +0x80000080, +0x00000000, +0x99006360, +0xdbd800f8, +0xdb9800f9, +0xc78000f8, +0x99006560, +0xdbd800f8, +0xdb9800f9, +0xc78000f8, +0xc2200058, +0xc0004948, +0xce021038, +0xc2000002, +0xc000494c, +0xce0000f8, +0xc2000006, +0xc0001006, +0xce0000f8, +0x5838000a, +0xca4000f8, +0xc2200982, +0x5a203b6e, +0xc0001008, +0xce0000f8, +0xc000100a, +0xce4000f8, +0xc0004954, +0xca8000f8, +0xc200000c, +0xc000494a, +0xce0000f8, +0xc0004948, +0xce800008, +0xc2b60000, +0xc0004964, +0xce8000f8, +0x99006220, +0xc00048a0, +0xc88400f8, +0x00000000, +0xc0004946, +0xcbc000f8, +0xc000494c, +0xca0000f8, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x5e200000, +0x840000fa, +0x00000000, +0x99005fe0, +0xdbd800f8, +0xdb9800f9, +0x00000000, +0x99005d28, +0xc000491c, +0xc1400000, +0xc9420048, +0xc000491c, +0x990061d8, +0xc94000f9, +0xc98000f8, +0x00000000, +0x99005f50, +0xd95800f8, +0xd99800f9, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0x99005c18, +0xdbd800f8, +0xdb9800f9, +0xc7d800f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0xc000493c, +0xca8000f8, +0xc000494e, +0xcac000f8, +0xc3000018, +0xc3400006, +0x5e200000, +0x8400002a, +0xc2800000, +0xc2c00000, +0xc300001e, +0xc3400000, +0xc6ac1078, +0xc72c0418, +0xc76c0810, +0x58380010, +0xca8000f8, +0x58380008, +0xcec000f8, +0xc6280100, +0xc0004874, +0xc80400f8, +0x6c908000, +0x45088000, +0x45088000, +0x40100000, +0xcb0000f8, +0xc43400f8, +0x00000000, +0xc74000f8, +0xce8000f8, +0xc0004952, +0xce8000f8, +0x00000000, +0x00000000, +0x00000000, +0xa8e2ffe8, +0x00000000, +0xc000494c, +0xca0000f8, +0xc0004950, +0xcac000f8, +0x5e200000, +0x8400006a, +0xdfe800f8, +0x7e814000, +0x5834001a, +0xce8000f8, +0x990066c8, +0xc0004834, +0xc94000f8, +0xc1800002, +0x990066c8, +0xc0004838, +0xc94000f8, +0xc6d800f8, +0xc1220002, +0xd90c00f8, +0x5e200000, +0x84000040, +0x5838002c, +0xcb0000f8, +0xdfe800f8, +0x00000000, +0x58380014, +0xcf0000f8, +0x80000018, +0xc2a1fffe, +0x5aa9fffe, +0x5838000a, +0xce8000f8, +0xc3000000, +0xc0000a14, +0xcb040028, +0xc2d00002, +0xc0000a28, +0xcec50800, +0xc000494e, +0xca8000f8, +0x58880002, +0xb4b00018, +0xc00048a0, +0xc0800000, +0xcc8400f8, +0x5ea80000, +0x84000152, +0x5e200000, +0x84000140, +0xc000493c, +0xca8000f8, +0x00000000, +0x00000000, +0x5aa80060, +0xce8000f8, +0x99006360, +0xdbd800f8, +0xdb9800f9, +0xc78000f8, +0x99006560, +0xdbd800f8, +0xdb9800f9, +0xc78000f8, +0xc0004952, +0xcac000f8, +0x58380000, +0xca8000f8, +0xc30c0002, +0xc7f00018, +0xa6800098, +0x00000000, +0x00000000, +0xc161fffe, +0x5955fffe, +0x14140000, +0x00000000, +0xc0001800, +0xca0000f8, +0x00000000, +0x00000000, +0xa60cffea, +0xc6f00500, +0xc6b0c400, +0xcf0000f8, +0x00000000, +0xc121ffee, +0x5911fe14, +0x14100000, +0x8000cb60, +0xdcbc00f9, +0x5ffc0000, +0x84000052, +0xc3800002, +0xdb8800f9, +0x5ffc0004, +0x8400bec0, +0xc3800000, +0xdb8800f9, +0xc3ce0002, +0xc0000800, +0xcfc0e700, +0xc3e1fffe, +0x597dffee, +0x593dfe14, +0x00000000, +0x00000000, +0x00000000, +0x94000001, +0x00000000, +0x00000000, +0x00000000, +0xc000487c, +0xc80400f8, +0x00000000, +0x00000000, +0x40080000, +0xcbc000f8, +0xc43800f8, +0x00000000, +0xc000480e, +0xca0000f8, +0xc0004858, +0xcb4400f8, +0x00000000, +0x00000000, +0x47610000, +0x880000b0, +0x00000000, +0xa7c00048, +0xc0004854, +0xc1000002, +0xcd0400f8, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0x800000d8, +0x00000000, +0xa7d20138, +0x00000000, +0xc7e14040, +0xc2400000, +0xc6246028, +0xc200006a, +0x46250000, +0xc6240030, +0xc0000810, +0xce440030, +0x8000ff70, +0xc2000000, +0xc0000808, +0xca040010, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0x5a200002, +0x5e600010, +0x84000010, +0xc2000000, +0xc0000808, +0xce040010, +0xc3400000, +0x80000028, +0xc1200002, +0xc0000818, +0xcd061000, +0x5b740002, +0xc0004858, +0xcf4400f8, +0x99005968, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc11c0002, +0xc000082c, +0xcd05ce00, +0x800005e0, +0x5b740002, +0xc0004858, +0xcf4400f8, +0xc78000f8, +0xc13c0002, +0xcd03de00, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc000082c, +0xc9840028, +0x59540002, +0xc0004848, +0xcd4400f8, +0x58880002, +0xb4980560, +0x00000000, +0xc0800000, +0x80000548, +0xc000487c, +0xc80400f8, +0x00000000, +0x00000000, +0x40080000, +0xcbc000f8, +0xc42800f8, +0x00000000, +0xa7c00130, +0xc000484c, +0xca0400f8, +0xc2400000, +0xc0001aec, +0xca440018, +0x5a200002, +0xc000484c, +0xce0400f8, +0xb624008a, +0xc68000f8, +0xc13c0002, +0xcd03de00, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc000082c, +0xc9840028, +0x59540002, +0xc0004848, +0xcd4400f8, +0x58880002, +0xb4980450, +0x00000000, +0xc0800000, +0x80000438, +0xc0004854, +0xc1000004, +0xcd0400f8, +0xc0000820, +0xc2000002, +0xce0400f8, +0xc2000000, +0xc000484c, +0xce0400f8, +0xc0004858, +0xce0400f8, +0x8000ff28, +0xc0004854, +0xc1000000, +0xcd0400f8, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0x99005968, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc1200000, +0xc0000818, +0xcd061000, +0xc11c0002, +0xc000082c, +0xcd05ce00, +0xc2000000, +0xc000484c, +0xce0400f8, +0x80000338, +0xc0001ac0, +0xcb8400f8, +0xc000487c, +0xc80400f8, +0x00000000, +0x00000000, +0x40080000, +0xcbc000f8, +0xc42800f8, +0x00000000, +0xa780024a, +0x00000000, +0x00000000, +0xa7c0020a, +0x00000000, +0xc0001b00, +0xc2060006, +0xce046308, +0xa7e801c2, +0x00000000, +0xc0004850, +0xca0400f8, +0xc2400000, +0xc0001aec, +0xca448018, +0x5a200002, +0xc0004850, +0xce0400f8, +0xb62400aa, +0x00000000, +0xc68000f8, +0xc13c0002, +0xcd03de00, +0xc0001acc, +0xc2000002, +0xce040000, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc000082c, +0xc9840028, +0x59540002, +0xc0004848, +0xcd4400f8, +0x58880002, +0xb49801c8, +0x00000000, +0xc0800000, +0x800001b0, +0xc0004854, +0xc1000000, +0xcd0400f8, +0xc11c0000, +0xc000082c, +0xcd05ce00, +0x99005968, +0xc0004848, +0xc94400f8, +0xc1800000, +0xc2000000, +0xc0000820, +0xce0400f8, +0xc1200000, +0xc0000818, +0xcd061000, +0xc11c0002, +0xc000082c, +0xcd05ce00, +0xc0004850, +0xce0400f8, +0xc2000002, +0xc0001acc, +0xce040008, +0x800000e8, +0xc2000002, +0xc0004850, +0xce0400f8, +0x8000fe88, +0xc2000000, +0xc0004850, +0xce0400f8, +0xa7e60032, +0x00000000, +0xc2000002, +0xc0001b00, +0xce040000, +0x8000fe70, +0x00000000, +0xa7860052, +0x00000000, +0xc68000f8, +0xc13c0002, +0xcd03de00, +0xc2020002, +0xc7e2a540, +0xc0001b00, +0xce0400f8, +0x8000fe18, +0xc2040002, +0xc0001b00, +0xce044200, +0x8000fdf8, +0xc2c80002, +0x6ac56000, +0xdacc00f8, +0xc0004854, +0xcb4400f8, +0xc0004848, +0xcb8400f8, +0xc0000838, +0xc3c00000, +0xcbc40028, +0x5ef40004, +0x84000022, +0xc3000000, +0xc0001acc, +0xcf042100, +0x47f98000, +0x8400002a, +0x47f98000, +0x88000030, +0xc1006e8c, +0x8000b300, +0xc0004840, +0xcc8400f8, +0x8000f6b8, +0xc0001ac0, +0xcac400f8, +0xc0004854, +0xcb4400f8, +0xa6c0fbf2, +0x00000000, +0x5ef40000, +0x8400f72a, +0x5ef40002, +0x8400f9ba, +0x5ef40004, +0x8400fbba, +0xc1006ce8, +0x8000b278, +0x00000000, +0xc0800000, +0xdf4b0038, +0xc0004900, +0xcb8000f8, +0xc2000000, +0xc000490a, +0xa78000d0, +0xcbc000f8, +0xc1000000, +0xd90000f9, +0xc1000002, +0xd90c00f8, +0x6ff46000, +0x477da000, +0x5b744c80, +0xc2400000, +0x58340004, +0xca400078, +0xc0004900, +0xce000000, +0x5a640002, +0x58340004, +0xc6500078, +0xcd000078, +0xc0004914, +0xca4000f8, +0xc2000002, +0x6a3d0000, +0x72612000, +0xce4000f8, +0xc0000408, +0xce0000f8, +0xa78200d8, +0xc0004908, +0xcbc000f8, +0xc1000000, +0xd90000f9, +0xc1000002, +0xd90c00f8, +0x6ff4a000, +0x6fd44000, +0x4755a000, +0x477da000, +0x5b745e00, +0xc2800000, +0x58340006, +0xca800078, +0xc2000000, +0xc0004900, +0xce002100, +0x5ea80002, +0x58340006, +0xc6900078, +0xcd000078, +0x5a7c0020, +0xc2000002, +0x6a250000, +0xc0000408, +0xce0000f8, +0xdca800f9, +0x5ea80000, +0x8400b0e8, +0x00000000, +0xa4800230, +0x00000000, +0xc3c00000, +0xc000140e, +0xcbc00018, +0xc3400000, +0xc2400000, +0x6ff86000, +0x47bdc000, +0x5bb84c80, +0x58380008, +0xcb400078, +0x58380006, +0xca400078, +0x5f740002, +0x58380008, +0xc7500078, +0xcd000078, +0xc2000000, +0x58380004, +0xca020078, +0xc3000000, +0x5838000c, +0xcb000020, +0x5a640002, +0x46610000, +0x84000010, +0xc2400000, +0x58380006, +0xc6500078, +0xcd000078, +0xc2000000, +0x5838000a, +0xca020078, +0x5b300002, +0x5838000c, +0xc7100020, +0xcd000020, +0xc2420020, +0x5a200004, +0x46252000, +0x84000010, +0xc2000000, +0x5838000a, +0xc6101078, +0xcd021078, +0xc0004966, +0xca4000f8, +0xc2000002, +0x6a3d0000, +0x72612000, +0xce4000f8, +0x5f740000, +0x84000040, +0xc0004912, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x7ec16000, +0x762d0000, +0xce0000f8, +0x5f300020, +0x84000040, +0xc0004924, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x7ec16000, +0x762d0000, +0xce0000f8, +0xa4820070, +0xc2400000, +0xc000140e, +0xca408018, +0xc2000002, +0xc0004900, +0xce000000, +0xc000490a, +0xce4000f8, +0xc1000000, +0xd90000f9, +0xd8400078, +0xc1000004, +0xd90000f9, +0xa48402a8, +0x00000000, +0xc3c00000, +0xc000140e, +0xcbc10018, +0xc2800000, +0xc2000000, +0x6ff8a000, +0x6fd44000, +0x4795c000, +0x47bdc000, +0x5bb85e00, +0x5838002e, +0xca800078, +0x58380006, +0xca020078, +0xc3400000, +0x5838002e, +0xcb420078, +0x5aa80002, +0x46a10000, +0x84000010, +0xc2800000, +0x5838002e, +0xc6900078, +0xcd000078, +0x5f740002, +0x5838002e, +0xc7501078, +0xcd021078, +0xc0004968, +0xca4000f8, +0xc2000002, +0x6a3d0000, +0x72612000, +0xce4000f8, +0xc000492a, +0xca8000f8, +0x5e740000, +0x84000040, +0xc0004910, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x7ec16000, +0x762d0000, +0xce0000f8, +0x6abd4010, +0xa68000f2, +0x00000000, +0xc0004910, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x7ec16000, +0x762d0000, +0xce0000f8, +0x58380032, +0xca0000f8, +0x58000002, +0xca4000f8, +0x5838000c, +0x00000000, +0xce0000f9, +0xce4000f8, +0xc000492a, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x722d0000, +0xce0000f8, +0xc000492c, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x722d0000, +0xce0000f8, +0x80000040, +0xc000492c, +0xca0000f8, +0xc2c00002, +0x6afd6000, +0x7ec16000, +0x762d0000, +0xce0000f8, +0xa4880120, +0xc2c00000, +0xc000140e, +0xcac20018, +0xc000490e, +0xca4000f8, +0xc2000002, +0x6a2d0000, +0x7e010000, +0x76612000, +0xce4000f8, +0xc000496a, +0xca4000f8, +0xc2000002, +0x6a2d0000, +0x72612000, +0xce4000f8, +0x6ef0a000, +0x6ed44000, +0x47158000, +0x472d8000, +0x5b305e00, +0x58300000, +0xca0000f8, +0x00000000, +0xc2400002, +0x76612000, +0x8400004a, +0xc24c0002, +0xc6e40018, +0xc624c400, +0x58300010, +0xca400500, +0x00000000, +0xc0001800, +0xce4000f8, +0xa4860070, +0xc2400000, +0xc000140e, +0xca418018, +0xc2020002, +0xc0004900, +0xce002100, +0xc0004908, +0xce4000f8, +0xc1000000, +0xd90000f9, +0xd8400078, +0xc1000004, +0xd90000f9, +0xc0001408, +0xcc8000f8, +0xc10e0002, +0xd90c00f8, +0x8000eda8, +0xdfbc00f9, +0xc000496e, +0x99006670, +0xc94000f8, +0xc7d800f8, +0x00000000, +0xc57000f8, +0x5ef00020, +0x88000148, +0x6f346000, +0x4771a000, +0x5b744c80, +0x58340008, +0xc2400000, +0xca400078, +0x00000000, +0xc2000000, +0x5a640002, +0xce400078, +0x58340004, +0xca000078, +0x00000000, +0x00000000, +0x5e200002, +0xce000078, +0xc0004912, +0xca8000f8, +0xc2400002, +0x6a712000, +0x72a54000, +0xce8000f8, +0x5e200000, +0x84000052, +0xc000480a, +0xca0000f8, +0xc0000408, +0xca8000f8, +0x76250000, +0x00000000, +0x72a14000, +0xce8000f8, +0x80000038, +0xc0004914, +0xca0000f8, +0x7e412000, +0x00000000, +0x76250000, +0xce0000f8, +0x800000d0, +0x6ef4a000, +0x6ed44000, +0x4755a000, +0x476da000, +0x5b745e00, +0x5834002e, +0xc2400000, +0xca420078, +0x00000000, +0xc2000000, +0x5a640002, +0xc6501078, +0xcd021078, +0x58340006, +0xca000078, +0x00000000, +0x00000000, +0x5a200002, +0xce000078, +0xc0004910, +0xca4000f8, +0xc2000002, +0x6a2d0000, +0x72612000, +0xce4000f8, +0xc2000002, +0x6a310000, +0xc000042a, +0xce0000f8, +0xc1040002, +0xd90c00f8, +0x00000000, +0x8000eb18, +0x00000000, +0xc4980928, +0x9d000000, +0xc5580028, +0xc0000838, +0xcd8400f8, +0xc1440200, +0xc1c01600, +0xc55c1070, +0xc000100e, +0x9d000000, +0xcd8000f8, +0xc000100c, +0xcdc000f8, +0xc0004862, +0xc9c000f8, +0x00000000, +0x00000000, +0xd9d800f9, +0xc0005600, +0x401c0000, +0x5dc05800, +0x88000012, +0x5c000200, +0xcd8000f8, +0xc1f0000a, +0x715ca000, +0xdd9800f8, +0xdd9c00f9, +0x41d8e000, +0xc5d40260, +0xc0001010, +0xcd4000f8, +0x6c9c8000, +0x45c8e000, +0x45c8e000, +0x59dc0004, +0xc1601260, +0xc5d40260, +0x9d000000, +0xc0001012, +0xcd4000f8, +0x00000000, +0x00000000, +0xd95800f8, +0x6d586000, +0x4594c000, +0x59984c80, +0xd99800f9, +0x5818000a, +0xc1800000, +0xc9800078, +0xc0005400, +0x6d5ca000, +0x401c0000, +0x40180000, +0xc94000f8, +0x58000002, +0x00000000, +0xc9c000f8, +0xc0004930, +0xcd4000f8, +0xc0004932, +0xcdc000f8, +0x59980004, +0xc1c20020, +0xb59c0018, +0x00000000, +0xc1800000, +0xdd9c00f9, +0x581c000a, +0xcd800078, +0x581c000c, +0xc1800000, +0xc9800020, +0xc1c00002, +0xdd9400f8, +0x69d4e000, +0x5d980002, +0xcd800020, +0xc0004924, +0xc98000f8, +0x00000000, +0x9d000000, +0x00000000, +0x719cc000, +0xcd8000f8, +0xc000492a, +0xc94000f8, +0xc1c00002, +0x69d8e000, +0x7dc0c000, +0x7558a000, +0xcd4000f8, +0xc000492c, +0xc94000f8, +0xdd8000f9, +0x58000032, +0x755ca000, +0x84000090, +0xc94000f9, +0xc98000f8, +0xdd8000f9, +0x5800000c, +0x00000000, +0xcd4000f9, +0xcd8000f8, +0xc000492c, +0xc94000f8, +0xc000492a, +0xc98000f8, +0x715ca000, +0xc000492c, +0xcd4000f8, +0x719cc000, +0xc000492a, +0xcd8000f8, +0x9d000000, +0x00000000, +0x00000000, +0x00000000, +0xc0004862, +0xc98000f8, +0x00000000, +0xc1c00200, +0x4194c000, +0x459ce000, +0x88000012, +0xc5d800f8, +0xc0004862, +0xcd8000f8, +0xc0001406, +0xc98000f8, +0xc1c00002, +0x9d000000, +0xc5d80a00, +0xc5581048, +0xcd8000f8, +0xc0004930, +0xc98000f8, +0xc0004932, +0xc9c000f8, +0xc140000e, +0xc5581c18, +0xdd9400f8, +0xc0005600, +0x40140000, +0x5d405800, +0x88000012, +0x5c000200, +0xcd8000f8, +0x58000002, +0x5d405800, +0x88000012, +0x5c000200, +0xcdc000f8, +0xdd5400f8, +0xc1c00000, +0x58140006, +0xc9c20078, +0xc1800000, +0x58140000, +0xc98000d8, +0x6ddc2000, +0xc000491e, +0x41d8e000, +0xcdc000f8, +0xdd9800f8, +0xc1c00022, +0xc5d80d70, +0xdd9400f9, +0xc5581c18, +0xc000491c, +0xcd8000f8, +0xdd5400f8, +0xc1c00000, +0x58140006, +0xc9c20078, +0xc1800000, +0x58140004, +0xc9820078, +0x00000000, +0x59dc0002, +0x45d8c000, +0x84000010, +0xc1c00000, +0x9d000000, +0x58140006, +0xc5d81078, +0xcd821078, +0xc0004860, +0xc94000f8, +0xc1800100, +0xc1d00002, +0x58146b00, +0xd58000f8, +0x58000002, +0xd58000f9, +0x59540004, +0xb5580018, +0xc0004860, +0xc1400000, +0xcd4000f8, +0xdd9800f9, +0x9d000000, +0xdd9400f8, +0xc0001404, +0xcdc10800, +0xc1c00000, +0xc1800200, +0x5d980004, +0xdf5d0048, +0x459ca000, +0x8800fff2, +0xdd8000f9, +0x5800000c, +0x00000000, +0xc94000f9, +0xc98000f8, +0xc1c00002, +0xc5d43f00, +0xc5d81e00, +0xc0004862, +0xc9c000f8, +0x00000000, +0x00000000, +0x581c5600, +0x5dc05800, +0x88000012, +0x5c000200, +0xcd4000f8, +0x58000002, +0x5dc05800, +0x88000012, +0x5c000200, +0xcd8000f8, +0xc0004862, +0xc9c000f8, +0x00000000, +0xc15004c0, +0xc5d40060, +0xdd9c00f8, +0xc5d41c18, +0xc1c00000, +0xdd8000f9, +0x58000030, +0xc9c00078, +0xdd8000f9, +0x58000002, +0xc98000f8, +0x6ddc2000, +0xc000491c, +0x41d8e000, +0xcd4000f9, +0xcdc000f8, +0xdd9400f9, +0xc1c00000, +0x58140030, +0xc9c00078, +0xc1800000, +0x58140006, +0xc9820078, +0x00000000, +0x59dc0002, +0x45d8c000, +0x84000010, +0xc1c00000, +0x9d000000, +0x58140030, +0xc5d80078, +0xcd800078, +0xc1c00000, +0xdf5c0038, +0x5ddc0080, +0x8400ffea, +0x00000000, +0x9d000000, +0x00000000, +0x00000000, +0x00000000, +0xc160fffe, +0xc0000a10, +0xc9440060, +0xc1a0fffe, +0x59981e08, +0xc000100c, +0xcd4000f8, +0xc000100e, +0xcd8000f8, +0xc0004964, +0xc98000f8, +0x00000000, +0xc170000a, +0x7158a000, +0x6c988000, +0x4588c000, +0x4588c000, +0x59980004, +0xc5940270, +0xc0001010, +0xcd4000f8, +0xc0004946, +0xc94000f8, +0x00000000, +0x00000000, +0x6d58a000, +0x6d5c4000, +0x459cc000, +0x4594c000, +0xc000494a, +0xc94000f8, +0xc0004948, +0xc9c000f8, +0x4194c000, +0xc1400012, +0xc55c1818, +0x9d000000, +0xc59c0268, +0xc0001012, +0xcdc000f8, +0xc1400000, +0x58000012, +0xc9410038, +0xc0004950, +0xc9c000f8, +0xc55800f8, +0xc5940838, +0xc5581078, +0xd99400f8, +0xc000493c, +0xc94000f8, +0xc0004954, +0xc98000f8, +0x59dc00a8, +0x45d4e000, +0x41d8e000, +0x5d5c0030, +0x88000010, +0xc1c00030, +0xc1800000, +0xc5d84028, +0xc1400000, +0xc5d40008, +0x5dd40002, +0x84000072, +0x5dd40004, +0x8400009a, +0x5dd40006, +0x840000c2, +0x5dd80026, +0x840000ea, +0xdd5400f8, +0xdd8000f9, +0x58000008, +0x40180000, +0xcd4000f8, +0x59980002, +0x8000ffc0, +0xdd5400f8, +0xdd8000f9, +0x58000008, +0x40180000, +0xcd4000b8, +0x59980002, +0x8000ff88, +0xdd5400f8, +0xdd8000f9, +0x58000008, +0x40180000, +0xcd400078, +0x59980002, +0x8000ff50, +0xdd5400f8, +0xdd8000f9, +0x58000008, +0x40180000, +0xcd400038, +0x59980002, +0x8000ff18, +0x00000000, +0x9d000000, +0x00000000, +0x00000000, +0x00000000, +0x58000012, +0xc94000f8, +0xc0004954, +0xc9c000f8, +0xc0004950, +0xc9400078, +0xdd8000f9, +0x58000028, +0x5d9c0000, +0x84000052, +0x5d9c0002, +0x84000052, +0x5d9c0004, +0x8400006a, +0xc55b0038, +0xc55c08b8, +0xcd800039, +0xcdc108b8, +0x80000060, +0xcd4000f8, +0x80000050, +0xc55900b8, +0xc55c1838, +0xcd8000b9, +0xcdc31838, +0x80000028, +0xc55a0078, +0xc55c1078, +0xcd800079, +0xcdc21078, +0x9d000000, +0x00000000, +0x00000000, +0x00000000, +0x59540002, +0x6994e018, +0x61c0c008, +0x4194a000, +0x5d940040, +0x88000012, +0xc59400f8, +0x9d000000, +0xcd4000f8, +0x00000000, +0x00000000, +0x9d000000, +0x4158a000, +0xcd4000f8, +0x00000000 +}; + +static unsigned int firmware_binary_data[] = { +}; + + +#endif // IFXMIPS_ATM_FW_AMAZON_SE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9.h new file mode 100644 index 0000000000..b22bcccca4 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9.h @@ -0,0 +1,439 @@ +#ifndef IFXMIPS_ATM_FW_AR9_H +#define IFXMIPS_ATM_FW_AR9_H + + +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_ar9.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 22 OCT 2007 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PP32 Firmware) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 22 OCT 2007 Xu Liang Initiate Version, v00.01 +*******************************************************************************/ + + +#define VER_IN_FIRMWARE 1 + +#define ATM_FW_VER_MAJOR 0 +#define ATM_FW_VER_MINOR 16 + + +static unsigned int firmware_binary_code[] = { + 0x800004b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000ffe0, 0x00000000, 0x00000000, 0x00000000, + 0xc1000002, 0xd90c00f8, 0xc2000002, 0xda0800f9, 0x80004980, 0xc2000000, 0xda0800f9, 0x80003fe8, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003fa0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80005178, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003ea0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0400000, 0xc0004840, 0xc88400f8, 0x80004640, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0400002, 0xc0004840, 0xc88400f8, 0x800045c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc3c00004, 0xdbc800f9, 0xc10c0002, 0xd90c00f8, 0x8000fee0, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc10e0002, 0xd90c00f8, 0xc0004808, 0xc84000f8, 0x800045f0, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc3e1fffe, 0x597dfffe, 0x593dfe14, 0x900004d9, 0x00000000, 0x00000000, 0x00000000, 0x90cc0481, + 0x00000000, 0x00000000, 0x00000000, 0xc3c00000, 0xdbc800f9, 0xc1400008, 0xc1900000, 0x71588000, + 0x14100100, 0xc140000a, 0xc1900002, 0x71588000, 0x14100100, 0xc140000c, 0xc1900004, 0x71588000, + 0x14100100, 0xc1400004, 0xc1900006, 0x71588000, 0x14100100, 0xc1400006, 0xc1900008, 0x71588000, + 0x14100100, 0xc140000e, 0xc190000a, 0x71588000, 0x14100100, 0xc1400000, 0xc190000c, 0x71588000, + 0x14100100, 0xc1400002, 0xc190000e, 0x71588000, 0x14100100, 0xc0400000, 0xc11c0000, 0xc000082c, + 0xcd05ce00, 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc0400002, 0xc11c0000, 0xc000082c, 0xcd05ce00, + 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc0000824, 0x00000000, 0xcbc000f9, 0xcb8000f9, 0xcb4000f9, + 0xcb0000f8, 0xc0004878, 0x5bfc4000, 0xcfc000f9, 0x5bb84000, 0xcf8000f9, 0x5b744000, 0xcf4000f9, + 0x5b304000, 0xcf0000f8, 0xc0000a10, 0x00000000, 0xcbc000f9, 0xcb8000f8, 0xc0004874, 0x5bfc4000, + 0xcfc000f9, 0x5bb84000, 0xcf8000f8, 0xc30001fe, 0xc000140a, 0xcf0000f8, 0xc3000000, 0x7f018000, + 0xc000042e, 0xcf0000f8, 0xc000040e, 0xcf0000f8, 0xc3c1fffe, 0xc000490e, 0xcfc00078, 0xc000492c, + 0xcfc00078, 0xc0004924, 0xcfc00038, 0xc0004912, 0xcfc00038, 0xc0004966, 0xcfc00038, 0xc0004968, + 0xcfc00078, 0xc000496a, 0xcfc00078, 0xc3c1fffe, 0xc00049a0, 0xcfc000f8, 0xc3c00000, 0xc2800020, + 0xc3000000, 0x7f018000, 0x6ff88000, 0x6fd44000, 0x4395c000, 0x5bb84a00, 0x5838000a, 0xcf0000f8, + 0x5bfc0002, 0xb7e8ffc8, 0x00000000, 0xc3c00000, 0xc2800010, 0x6ff86000, 0x47bdc000, 0x5bb84c80, + 0xc3400000, 0x58380004, 0xcb420078, 0x00000000, 0x58380008, 0xcf400078, 0x5bfc0002, 0xb7e8ffb0, + 0x00000000, 0xc3c00000, 0xc2800020, 0xc348001e, 0xc3000000, 0x7f018000, 0x6ff8a000, 0x6fd44000, + 0x4795c000, 0x47bdc000, 0x5bb87000, 0x58380008, 0xcf408418, 0x5838000a, 0xcf0000f8, 0x5bfc0002, + 0xb7e8ffb0, 0x00000000, 0x00000000, 0xc3e0a242, 0x5bfc0020, 0xc0004002, 0xcfc000f8, 0x00000000, + 0xc121fffe, 0x5911fe14, 0x14100000, 0x80000530, 0x00000000, 0x80002130, 0x00000000, 0x8000ffe0, + 0xc0004958, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000, 0xcc4000f8, 0xc0004848, 0xcb8400f8, + 0xc000495c, 0xcac400f8, 0xc0004844, 0xc88400f8, 0x47ad0000, 0x8400ff82, 0xc000487c, 0xc80400f8, + 0x00000000, 0x00000000, 0x40080000, 0xca0000f8, 0xc0001624, 0xcb0400f8, 0xa63c007a, 0x00000000, + 0x00000000, 0xa71eff22, 0x00000000, 0xc0000824, 0xca8400f8, 0x6ca08000, 0x6ca42000, 0x46250000, + 0x42290000, 0xc35e0002, 0xc6340060, 0xc0001624, 0xcf440078, 0xc2000000, 0xc161fffe, 0x5955fffe, + 0x14140000, 0x00000000, 0xc0004844, 0xc88400f8, 0xc000082c, 0xca040038, 0x00000000, 0x00000000, + 0x58880002, 0xb6080018, 0x00000000, 0xc0800000, 0xc0004844, 0xcc840038, 0x5aec0002, 0xc000495c, + 0xcec400f8, 0x5e6c0006, 0x84000060, 0xc0004848, 0xcb8400f8, 0xc0000838, 0xc2500002, 0xce450800, + 0x5fb80002, 0xc0004848, 0xcf8400f8, 0x5eec0002, 0xc000495c, 0xcec400f8, 0x00000000, 0xc121fffe, + 0x5911fe14, 0x14100000, 0x8000fd98, 0xc000495a, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000, + 0xcc4000f8, 0xc0004960, 0xcac400f8, 0x00000000, 0x00000000, 0x5eec0000, 0x8400010a, 0x00000000, + 0xb6fc0050, 0xc0001600, 0xca0400f8, 0x00000000, 0x00000000, 0xa61e00d2, 0x6fe90000, 0xc0000a28, + 0xce850800, 0xc2c00000, 0xc2800004, 0xb6e800a0, 0xc0001604, 0xca8400f8, 0xc0004960, 0xcec400f8, + 0xa69efcc2, 0x00000000, 0x6fe90000, 0xc0000a28, 0xce850800, 0xc2c00002, 0xc0001600, 0xca0400f8, + 0x00000000, 0x00000000, 0xa61e002a, 0x6fe90000, 0xc0000a28, 0xce850800, 0xc2c00000, 0xc0001604, + 0xca8400f8, 0xc0004960, 0xcec400f8, 0xa69efc2a, 0xc2400000, 0xc0000a14, 0xca440028, 0x00000000, + 0x00000000, 0x466d2000, 0xa4400020, 0xc2800000, 0xdfeb0029, 0x80000010, 0xdfea0029, 0xb668fba2, + 0x00000000, 0xc00048a0, 0xcb0400f8, 0xc0000a10, 0xca8400f8, 0x6f208000, 0x6f242000, 0x46250000, + 0x42a10000, 0xc2400000, 0xc0000a14, 0xca440028, 0xc35e0002, 0xc6340060, 0xc0001604, 0xcf440078, + 0x5b300002, 0xb6700018, 0x5aec0002, 0xc3000000, 0xc00048a0, 0xcf0400f8, 0xc0004960, 0xcec400f8, + 0x8000fad8, 0xc0004918, 0xd28000f8, 0xc2000000, 0xdf600038, 0x5e600080, 0x84000272, 0x00000000, + 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000480a, 0xca0000f8, 0xc0004912, 0xca4000f8, + 0xc0004924, 0xca8000f8, 0xc0004966, 0xcac000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, + 0x76250000, 0x76290000, 0x762d0000, 0x840001ca, 0xc0004918, 0xca4000f8, 0xc28001fe, 0x76290000, + 0x5a640002, 0x6a254010, 0x5ee80000, 0x8400001a, 0x6aa54000, 0x80000010, 0xc62800f8, 0x62818008, + 0xc0004918, 0xcf0000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0004966, 0xca4000f8, + 0xc2000002, 0x6a310000, 0x7e010000, 0x76612000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, + 0x14100000, 0x6f346000, 0x4771a000, 0x5b744c80, 0xc2800000, 0x58340006, 0xca800078, 0xc2c00000, + 0x58340000, 0xcac000d8, 0xc2400000, 0x5834000a, 0xca420078, 0x6ea82000, 0x42e9e000, 0x6f2ca000, + 0x42e56000, 0x5aec2e00, 0xc3990040, 0xc7381c18, 0xc6f80060, 0x99005b78, 0xdb9800f8, 0xdbd800f9, + 0x00000000, 0xdea000f8, 0x46310000, 0x8400fd80, 0xc0004958, 0xc84000f8, 0x00000000, 0xc3c00002, + 0x787c2000, 0xcc4000f8, 0xc0004848, 0xcb8400f8, 0xc0004844, 0xc88400f8, 0x5fb80000, 0x8400f7f2, + 0xc0001a1c, 0xca0000f8, 0xc2400002, 0x6a452000, 0x76250000, 0x8400f7c2, 0xc000487c, 0xc80400f8, + 0x00000000, 0x00000000, 0x40080000, 0xca0000f8, 0xc42400f8, 0x00000000, 0xa63c17da, 0x00000000, + 0xc0004878, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000, 0xca0000f8, 0xc42400f8, + 0x00000000, 0xc0004934, 0xce0000f8, 0xc2800002, 0xc4681c08, 0xc62821d0, 0xc2600010, 0x5a650060, + 0xc0004800, 0xcb4000f8, 0xc2200400, 0x5a200020, 0xc7601040, 0xc0001220, 0xce8000f8, 0xc0001200, + 0xce4000f8, 0xc0001202, 0xce0000f8, 0xc0001240, 0xcb4000f8, 0x00000000, 0x00000000, 0xa754ffe0, + 0xc2000000, 0xc7600040, 0xa7520042, 0x00000000, 0x00000000, 0x990062f0, 0xc0004822, 0xc94000f8, + 0xc1800002, 0x80001680, 0x582040a0, 0xc2000000, 0xca000018, 0xc2400000, 0xca414000, 0xc2800000, + 0xca812000, 0xc2c00000, 0xcac20018, 0xc0004938, 0xce0000f8, 0xc0004920, 0xce4000f8, 0xc0004916, + 0xce8000f8, 0xc0004922, 0xcec000f8, 0xa6400540, 0x00000000, 0xc0004938, 0xcbc000f8, 0x00000000, + 0xc3800000, 0x6ff48000, 0x6fd44000, 0x4355a000, 0x5b744a00, 0x58340000, 0xcb802010, 0x00000000, + 0xc2000000, 0x6fb46000, 0x4779a000, 0x5b744c80, 0x5834000c, 0xca000020, 0xc000491a, 0xcf8000f8, + 0x5e200000, 0x8400046a, 0xc2000000, 0xdf610048, 0x5e6001e8, 0x8800ffe8, 0xc2000002, 0xc2400466, + 0xc2a00000, 0x5aa80000, 0xc0001006, 0xce0000f8, 0xc0001008, 0xce4000f8, 0xc000100a, 0xce8000f8, + 0x990055b8, 0xc1a0fffe, 0xc0000824, 0xc9840060, 0xc0004934, 0xca4000f8, 0xc2000000, 0xc2800002, + 0x990055f8, 0xda9800f8, 0xc61400f8, 0xc65800f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, + 0x990056e0, 0xc000491a, 0xc94000f8, 0x00000000, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, + 0xc0004922, 0xca001118, 0xc3c00000, 0xc3800000, 0xc0004930, 0xce023118, 0xc0004932, 0xcbc000d8, + 0xc2800000, 0xc000491e, 0xcfc000f8, 0xc0004862, 0xca800060, 0xc3a0001a, 0x5bb94000, 0xc6b80060, + 0xc000491c, 0xcf8000f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0x00000000, 0x00000000, + 0x00000000, 0xa8e2ffe8, 0xc2000000, 0xc1220002, 0xd90c00f8, 0xdf600038, 0x5e600080, 0x8400fff2, + 0xc000491c, 0xca0000f8, 0xc000491e, 0xca4000f8, 0x00000000, 0x00000000, 0x99005b78, 0xda1800f8, + 0xda5800f9, 0x00000000, 0xc2000000, 0xdf610048, 0x5e6001fe, 0x8800ffe8, 0xc0004916, 0xca8000f8, + 0xc2c00000, 0xdfec0048, 0xc2400000, 0x466d2000, 0x8400004a, 0x5ea80000, 0x8400003a, 0xc2600002, + 0x990062f0, 0xc000482e, 0xc94000f8, 0xc1800002, 0x80000030, 0xc2600000, 0x990062f0, 0xc000482c, + 0xc94000f8, 0xc1800002, 0xc2000068, 0xc6240078, 0xc0004930, 0xce400080, 0xc000491a, 0xc98000f8, + 0xc0004862, 0xc94000f8, 0x6d9c6000, 0x45d8e000, 0x59dc4c80, 0x990059d8, 0xd95800f8, 0xd99800f9, + 0xd9d400f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0xc2000000, 0xdf600038, 0x5e600080, + 0x8400ffea, 0x00000000, 0xc000491c, 0xca0000f8, 0xc000491e, 0xca4000f8, 0x00000000, 0x00000000, + 0x99005b78, 0xda1800f8, 0xda5800f9, 0x00000000, 0x800010e8, 0x00000000, 0x990062f0, 0xc000482a, + 0xc94000f8, 0xc1800002, 0x800010b8, 0xc0004938, 0xcbc000f8, 0x00000000, 0x00000000, 0x6ff88000, + 0x6fd44000, 0x4395c000, 0x5bb84a00, 0x58380008, 0xca0000f8, 0x00000000, 0x00000000, 0xa6000382, + 0x00000000, 0xc0004938, 0xcbc000f8, 0xc3000000, 0x00000000, 0x6ff88000, 0x6fd44000, 0x4395c000, + 0x5bb84a00, 0x58380000, 0xcb002010, 0xc2000000, 0x58380008, 0xca020078, 0x5838000c, 0xcac000f8, + 0x5838000e, 0xca4000f8, 0xc000491a, 0xcf0000f8, 0xc0004930, 0xcec000f8, 0xc000493c, 0xce0000f8, + 0xc0004932, 0xce4000f8, 0x5e200000, 0x84000120, 0xc2800000, 0xa6fe00ba, 0x6f206000, 0x46310000, + 0x5a204c80, 0x5820000c, 0xca800020, 0x00000000, 0x00000000, 0x5ea80000, 0x840001f2, 0x00000000, + 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x990056e0, 0xc000491a, 0xc94000f8, 0x00000000, + 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc0004930, 0xcac000f8, 0xc0004932, 0xca4000f8, + 0xc7ec1118, 0xc0004930, 0xcec000f8, 0x5838000c, 0xcec000f8, 0x58000002, 0xce4000f8, 0xc0004934, + 0xca0000f8, 0xc2400002, 0x6e642000, 0x6e642000, 0x76612000, 0x8400002a, 0xc2400002, 0x6e684000, + 0x58380008, 0xce804200, 0xa6000020, 0x6e682000, 0x58380008, 0xce802100, 0xc2400002, 0x6e642000, + 0x76612000, 0x840000ea, 0x58380008, 0xca0000f8, 0xc2800000, 0xc2400000, 0xa60200c0, 0xdba800f8, + 0x6f386000, 0x47b1c000, 0x5bb84c80, 0x58380004, 0xca400078, 0x58380002, 0xca800078, 0x00000000, + 0xdeb800f8, 0x46a54000, 0x88000060, 0x00000000, 0xc0004824, 0xca0000f8, 0xc2400002, 0x6e640000, + 0x5a200002, 0xce0000f8, 0x58380008, 0xce400000, 0x80000018, 0x00000000, 0x80000048, 0xc0004934, + 0xca0000f8, 0x00000000, 0x00000000, 0xa6020c6a, 0x00000000, 0x00000000, 0x80000c98, 0xc2800000, + 0xc2000200, 0xc240001a, 0xdf690048, 0x46294000, 0x46a54000, 0x8800ffd2, 0xc2000006, 0xc2600982, + 0x5a643b6e, 0x5838000a, 0xca8000f8, 0xc0001006, 0xce0000f8, 0xc0001008, 0xce4000f8, 0xc000100a, + 0xce8000f8, 0x990055b8, 0xc1a0fffe, 0xc0000824, 0xc9840060, 0xc2000000, 0xc0004930, 0xca02e008, + 0x58380026, 0xca4000f8, 0x00000000, 0xc2800000, 0x990055f8, 0xda9800f8, 0xc61400f8, 0xc65800f8, + 0xc0004934, 0xca0000f8, 0x00000000, 0x00000000, 0xa6020022, 0x00000000, 0x00000000, 0x80000318, + 0xc0004938, 0xcbc000f8, 0xc0004878, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000, + 0xca0000f8, 0xc42400f8, 0x00000000, 0x58240018, 0xca0000f8, 0x6ff88000, 0x6fd44000, 0x4395c000, + 0x5bb84a00, 0xc3000000, 0xc3400002, 0xc2c00000, 0xc62c0078, 0xc6270038, 0xc0004940, 0xce400038, + 0xc6260038, 0xc0004942, 0xce400038, 0xc000493c, 0xca0000f8, 0x5eec0000, 0x8400018a, 0x5a6c0010, + 0x46254000, 0x88000190, 0x5a600052, 0x46e54000, 0x88000178, 0x58380006, 0xca8000f8, 0xc0004940, + 0xca0000f8, 0xc2400000, 0xc6a70038, 0x7e412000, 0x76612000, 0xc2000000, 0xc6a10038, 0x46250000, + 0x84000138, 0xc0004942, 0xca0000f8, 0xc2400000, 0xc6a60038, 0x7e412000, 0x76612000, 0xc2000000, + 0xc6a00038, 0x58380002, 0xca8000f8, 0x46250000, 0x840000e8, 0xc2400000, 0xc6a60078, 0x466d0000, + 0x880000da, 0xc2400000, 0xc6a40078, 0x58380008, 0xca8000f8, 0x46e50000, 0x880000ba, 0x00000000, + 0xa6820018, 0x00000000, 0xc7700b00, 0xa6840098, 0x00000000, 0xc7700a00, 0x80000080, 0xc7700200, + 0xc000493c, 0xcac000f8, 0x80000060, 0xc7700300, 0xc000493c, 0xcac000f8, 0x80000040, 0xc7700900, + 0x80000030, 0xc7700800, 0x80000020, 0xc7700700, 0x80000010, 0xc7700500, 0xc0004944, 0xcf0000f8, + 0xc000493e, 0xcec000f8, 0xc0004938, 0xca4000f8, 0xc000493c, 0xcb8000f8, 0xc000493e, 0xcb4000f8, + 0xc3000000, 0x6e608000, 0x6e544000, 0x42150000, 0x5a204a00, 0x5aa00008, 0x58200004, 0xcb000078, + 0xc0004934, 0xca0000f8, 0xc2400000, 0xc0004930, 0xca42e008, 0xc3c00018, 0xa6020098, 0x00000000, + 0x43656000, 0x47ad0000, 0x88000050, 0x46f96000, 0x6ee04010, 0x5be00004, 0xc2000000, 0xc6e00008, + 0x5e200000, 0x84000042, 0x5bfc0002, 0x80000030, 0xc3c00004, 0x5a2c0008, 0x47a10000, 0x88000012, + 0x5fb80008, 0x6fe04000, 0x42390000, 0x47212000, 0x88000068, 0xc2400000, 0xc0004930, 0xca42e008, + 0xc2060002, 0xc68000f8, 0xce006300, 0x6fe04000, 0x4721c000, 0x5f700010, 0x4765a000, 0xc2000000, + 0xc6340008, 0xc25a000a, 0xc000491a, 0xca401c18, 0xc2800000, 0xc0004932, 0xca8000d8, 0xc0004862, + 0xca400060, 0x6fa04010, 0x42290000, 0xc000491e, 0xce0000f8, 0xc7e41048, 0xc000491c, 0xce4000f8, + 0x6fe04000, 0x43a1c000, 0xc000493c, 0xcf8000f8, 0xc000493e, 0xcf4000f8, 0xc000493a, 0xcfc000f8, + 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0xc2000000, 0xdce000f8, 0xa622ffd8, 0xc1220002, + 0xd90c00f8, 0xc0004938, 0xcbc000f8, 0xc0004944, 0xcb4000f8, 0xc0004862, 0xcb0000f8, 0xc0004934, + 0xca0000f8, 0x6ff88000, 0x6fd44000, 0x4395c000, 0x5bb84a00, 0xa6020268, 0xc2400000, 0x58380008, + 0xca406000, 0xdfe800f8, 0xc2218e08, 0x5a21baf6, 0x46a14000, 0x84000022, 0xc2080002, 0x7361a000, + 0x80000058, 0x5e640000, 0x84000022, 0xc20c0002, 0x7361a000, 0x80000030, 0xc2000000, 0xc760e710, + 0xc7604218, 0x5e200000, 0x84000272, 0xc2200002, 0xc0004930, 0xce021000, 0x990062f0, 0xc0004828, + 0xc94000f8, 0xc1800002, 0x58380000, 0xca0000f8, 0x00000000, 0x00000000, 0xa6000132, 0xc0004940, + 0xca8000f8, 0xc0004942, 0xca4000f8, 0xc7600078, 0xc6a01838, 0xc6601038, 0xc000493a, 0xca4000f8, + 0xc0004934, 0xca8000f8, 0xc0007800, 0x40300000, 0x40240000, 0x5c000004, 0x5ec07a00, 0x88000012, + 0x5c000200, 0xce0000f8, 0x58000002, 0x5ec07a00, 0x88000012, 0x5c000200, 0xce8000f8, 0xc000493e, + 0xca0000f8, 0xc2400000, 0x5838000c, 0xce4000f8, 0x990062f0, 0xc0004830, 0xc94000f8, 0xc61800f8, + 0xc0004930, 0xc6100078, 0xcd000078, 0x800000a8, 0xc2400002, 0x58380008, 0xce400000, 0xc0004944, + 0xcf4000f8, 0x80000278, 0xc000493c, 0xca4000f8, 0xdfe800f8, 0x5a300018, 0xc0007800, 0x40200000, + 0xca0000f8, 0x58380008, 0xc6501078, 0xcd021078, 0x5838000a, 0xce8000f8, 0x58380026, 0xce0000f8, + 0xc0004944, 0xcf4000f8, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0x80000038, 0x00000000, + 0x990062f0, 0xc0004826, 0xc94000f8, 0xc1800002, 0x8000fdd8, 0xc2000000, 0xc2400080, 0xdf600038, + 0xb624ffea, 0xc000491c, 0xca4000f8, 0xc000491e, 0xca8000f8, 0x99005b78, 0xda5800f8, 0xda9800f9, + 0x00000000, 0xc0004934, 0xca0000f8, 0x00000000, 0xc2800000, 0xa6020160, 0xc2400004, 0xc2000200, + 0xdf690048, 0x46294000, 0x46a54000, 0x8800ffda, 0x00000000, 0xc000491a, 0xc98000f8, 0xc0004862, + 0xc94000f8, 0x6d9c6000, 0x45d8e000, 0x59dc4c80, 0x990059d8, 0xd95800f8, 0xd99800f9, 0xd9d400f8, + 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, 0xc2000000, 0xc2400080, 0xdf600038, 0xb624ffea, + 0xc000491c, 0xca4000f8, 0xc000491e, 0xca8000f8, 0x99005b78, 0xda5800f8, 0xda9800f9, 0x00000000, + 0x58380008, 0xca4000f8, 0xc2000000, 0xce000018, 0xc2a1fffe, 0x5aa9fffe, 0xce021078, 0x5838000a, + 0xce8000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0000838, 0xc2500002, 0xce450800, + 0xc0004848, 0xcb8400f8, 0xc2000000, 0xc000082c, 0xca040028, 0x5fb80002, 0xc0004848, 0xcf8400f8, + 0x58880002, 0xb6080018, 0x00000000, 0xc0800000, 0xc0004844, 0xcc8400f8, 0x00000000, 0xc121fffe, + 0x5911fe14, 0x14100000, 0x8000ded8, 0xc2000000, 0xdf600038, 0x5e200080, 0x8400026a, 0x00000000, + 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000480c, 0xca0000f8, 0xc0004910, 0xca4000f8, + 0xc000492c, 0xca8000f8, 0xc0004968, 0xcac000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, + 0x76250000, 0x76290000, 0x76e16000, 0x840001c2, 0xc0004926, 0xca4000f8, 0xc201fffe, 0x76e16000, + 0x5a640002, 0x6ae50010, 0x5f200000, 0x8400001a, 0x6a250000, 0x80000010, 0xc6e000f8, 0x62014008, + 0xc0004926, 0xce8000f8, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0004968, 0xca4000f8, + 0xc2000002, 0x6a290000, 0x7e010000, 0x76612000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, + 0x14100000, 0x6eb4a000, 0x6e944000, 0x4755a000, 0x4769a000, 0x5b747000, 0x58340002, 0xc2000000, + 0xca0000d8, 0x5834002e, 0xc2400000, 0xca400078, 0x6eb0a000, 0x6ebc4000, 0x473d8000, 0x47298000, + 0x5b30302e, 0x5b300004, 0x6e642000, 0x4225e000, 0xc39a8024, 0xc7380060, 0xc6b81c18, 0x99005b78, + 0xdb9800f8, 0xdbd800f9, 0x00000000, 0xc2000000, 0xdf600038, 0x5e200080, 0x84000352, 0x00000000, + 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca0000f8, 0xc00049a0, 0xca8000f8, + 0xc000492a, 0xca4000f8, 0xc000496a, 0xcb0000f8, 0xc0004956, 0xcac000f8, 0x00000000, 0xc121fffe, + 0x5911fe14, 0x14100000, 0x77218000, 0x77258000, 0x77298000, 0x8400029a, 0xc201fffe, 0x77218000, + 0x5aec0002, 0x6b2d0010, 0x5ea00000, 0x8400001a, 0x6a2d0000, 0x80000010, 0xc72000f8, 0x62016008, + 0xc0004956, 0xcec000f8, 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000, 0x5b747000, 0x58340000, + 0xc9c000f8, 0xc00049a0, 0xca0000f8, 0xc3000000, 0xc5f04018, 0xc2400000, 0xc5e50038, 0x7e412000, + 0x76250000, 0xce0000f8, 0xc0004980, 0x40300000, 0xcec000f8, 0xc161fffe, 0x5955fffe, 0x14140000, + 0x00000000, 0xc000496a, 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x7e010000, 0x76612000, 0xce4000f8, + 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000, + 0x5b747000, 0x5834000e, 0xc2000000, 0xca0000d8, 0x58340008, 0xc2400000, 0xca420078, 0x5834000c, + 0xc2800000, 0xca832010, 0x6e644010, 0x42250000, 0x4229e000, 0xc39a8008, 0x58340008, 0xcb809018, + 0x58340008, 0xc2800000, 0xca810010, 0x6ee0a000, 0x6ee44000, 0x46250000, 0x462d0000, 0x5a200008, + 0x5a203008, 0x42290000, 0xc6380060, 0xc6f81c18, 0x99005b78, 0xdb9800f8, 0xdbd800f9, 0x00000000, + 0xc000495a, 0xc84000f8, 0x00000000, 0xc3c00002, 0x787c2000, 0xcc4000f8, 0xc0001a1c, 0xca0000f8, + 0xc2400008, 0x6a452000, 0x76250000, 0x84000ec2, 0xc0000a28, 0xc3800000, 0xcb840028, 0xc0000a14, + 0xc3400000, 0xcb440028, 0xc0004880, 0xcb0400f8, 0xb7b40072, 0x58041802, 0xcac000f8, 0xa7000078, + 0x00000000, 0x00000000, 0xa6c8d808, 0xc1000000, 0xc6d00018, 0xc0004980, 0x40100000, 0xca8000f8, + 0x80000070, 0x00000000, 0x00000000, 0x00000000, 0x8000d7b8, 0x00000000, 0xc2800000, 0xc7282018, + 0xc000490e, 0xca4000f8, 0x6be9e000, 0x00000000, 0x767d2000, 0x8400d770, 0x6ea0a000, 0x6e944000, + 0x46150000, 0x46290000, 0x5a207000, 0x5820000c, 0xca0000f8, 0xc0004946, 0xce8000f8, 0xa62203a8, + 0x00000000, 0xc2200060, 0xc0004948, 0xce000008, 0xce021038, 0xc240000a, 0xc000494a, 0xce4000f8, + 0xc2b60002, 0xc0004964, 0xce837b00, 0x99005e48, 0xc00048a0, 0xc88400f8, 0x00000000, 0xc0004946, + 0xcbc000f8, 0x00000000, 0x00000000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, 0x5bb87000, + 0x99005c08, 0xdbd800f8, 0xdb9800f9, 0x00000000, 0x99005950, 0xc000491c, 0xc1400000, 0xc9420048, + 0xc000491c, 0x99005e00, 0xc94000f9, 0xc98000f8, 0x00000000, 0x99005b78, 0xd95800f8, 0xd99800f9, + 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x99005840, 0xdbd800f8, 0xdb9800f9, + 0xc7d800f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ff8a000, 0x6fd44000, 0x4795c000, + 0x47bdc000, 0x5bb87000, 0x58380010, 0xca0000f8, 0xc0004874, 0xc80400f8, 0x6c908000, 0x45088000, + 0x45088000, 0x40100000, 0xca4000f8, 0xc43400f8, 0x00000000, 0xc74000f8, 0xce0000f8, 0xc161fffe, + 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x72692000, + 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x990062f0, 0xc0004836, 0xc94000f8, + 0xc1800002, 0x00000000, 0x00000000, 0x00000000, 0xa8e2ffe8, 0x00000000, 0x58380000, 0xc90000f8, + 0xc00049a0, 0xca0000f8, 0xc2800000, 0xc5290038, 0x72290000, 0xce0000f8, 0xc1220002, 0xd90c00f8, + 0xc2000000, 0xc0000a14, 0xca040028, 0xc0000a28, 0xc2500002, 0xce450800, 0x58880002, 0xb6080018, + 0xc00048a0, 0xc0800000, 0xcc8400f8, 0x8000d380, 0xc0004946, 0xcbc000f8, 0xc161fffe, 0x5955fffe, + 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x72692000, 0xce4000f8, + 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, + 0x5bb87000, 0x58380008, 0xca0000f8, 0x5838000c, 0xca4000f8, 0xc3400000, 0xc6340000, 0xc000494e, + 0xcf4000f8, 0xc2800000, 0xc62a0078, 0xc3000000, 0xc6308018, 0x6f304000, 0x43298000, 0xc000493c, + 0xcf0000f8, 0xc2c00000, 0xc66c0078, 0xc0004950, 0xcec000f8, 0xc2800000, 0xc66ae020, 0xc0004954, + 0xce8000f8, 0x5f740000, 0x840001a0, 0x5e300028, 0x46e12000, 0x8400016a, 0x46e12000, 0x88000132, + 0x5e300018, 0x46e12000, 0x8800002a, 0x46e12000, 0x84000042, 0x00000000, 0x800000c0, 0x00000000, + 0x99005f88, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0xc3400002, 0xc000494e, 0xcf4000f8, 0xc161fffe, + 0x5955fffe, 0x14140000, 0x00000000, 0xc000490e, 0xca4000f8, 0xc2800002, 0x6abd4000, 0x7e814000, + 0x76692000, 0xce4000f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc2200060, 0xc0004948, + 0xce021038, 0xc2000000, 0xc000494c, 0xce0000f8, 0x80000080, 0x00000000, 0x99005f88, 0xdbd800f8, + 0xdb9800f9, 0xc78000f8, 0x99006188, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0xc2200058, 0xc0004948, + 0xce021038, 0xc2000002, 0xc000494c, 0xce0000f8, 0xc2000006, 0xc0001006, 0xce0000f8, 0x5838000a, + 0xca4000f8, 0xc2200982, 0x5a203b6e, 0xc0001008, 0xce0000f8, 0xc000100a, 0xce4000f8, 0xc0004954, + 0xca8000f8, 0xc200000c, 0xc000494a, 0xce0000f8, 0xc0004948, 0xce800008, 0xc2b60000, 0xc0004964, + 0xce8000f8, 0x99005e48, 0xc00048a0, 0xc88400f8, 0x00000000, 0xc0004946, 0xcbc000f8, 0xc000494c, + 0xca0000f8, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, 0x5bb87000, 0x5e200000, 0x840000fa, + 0x00000000, 0x99005c08, 0xdbd800f8, 0xdb9800f9, 0x00000000, 0x99005950, 0xc000491c, 0xc1400000, + 0xc9420048, 0xc000491c, 0x99005e00, 0xc94000f9, 0xc98000f8, 0x00000000, 0x99005b78, 0xd95800f8, + 0xd99800f9, 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0x99005840, 0xdbd800f8, + 0xdb9800f9, 0xc7d800f8, 0x00000000, 0xc121fffe, 0x5911fe14, 0x14100000, 0xc000493c, 0xca8000f8, + 0xc000494e, 0xcac000f8, 0xc3000018, 0xc3400006, 0x5e200000, 0x8400002a, 0xc2800000, 0xc2c00000, + 0xc300001e, 0xc3400000, 0xc6ac1078, 0xc72c0418, 0xc76c0810, 0x58380010, 0xca8000f8, 0x58380008, + 0xcec000f8, 0xc6280100, 0xc0004874, 0xc80400f8, 0x6c908000, 0x45088000, 0x45088000, 0x40100000, + 0xcb0000f8, 0xc43400f8, 0x00000000, 0xc74000f8, 0xce8000f8, 0xc0004952, 0xce8000f8, 0x00000000, + 0x00000000, 0x00000000, 0xa8e2ffe8, 0x00000000, 0xc000494c, 0xca0000f8, 0xc0004950, 0xcac000f8, + 0x5e200000, 0x8400006a, 0xdfe800f8, 0x7e814000, 0x5834001a, 0xce8000f8, 0x990062f0, 0xc0004834, + 0xc94000f8, 0xc1800002, 0x990062f0, 0xc0004838, 0xc94000f8, 0xc6d800f8, 0xc1220002, 0xd90c00f8, + 0x5e200000, 0x84000040, 0x5838002c, 0xcb0000f8, 0xdfe800f8, 0x00000000, 0x58380014, 0xcf0000f8, + 0x80000058, 0xc2a1fffe, 0x5aa9fffe, 0x58380000, 0xc90000f8, 0xc00049a0, 0xcb0000f8, 0xc2c00000, + 0xc52d0038, 0x732d8000, 0xcf0000f8, 0x5838000a, 0xce8000f8, 0xc3000000, 0xc0000a14, 0xcb040028, + 0xc2d00002, 0xc0000a28, 0xcec50800, 0xc000494e, 0xca8000f8, 0x58880002, 0xb4b00018, 0xc00048a0, + 0xc0800000, 0xcc8400f8, 0x5ea80000, 0x8400017a, 0x5e200000, 0x84000168, 0xc000493c, 0xca8000f8, + 0x00000000, 0x00000000, 0x5aa80060, 0xce8000f8, 0x99005f88, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, + 0x99006188, 0xdbd800f8, 0xdb9800f9, 0xc78000f8, 0x58380000, 0xcac000f8, 0x00000000, 0xc2000000, + 0xc6e04018, 0xc0004952, 0xcac000f8, 0x58380000, 0xca8000f8, 0xc30c0002, 0xc6300018, 0xa6800098, + 0x00000000, 0x00000000, 0xc161fffe, 0x5955fffe, 0x14140000, 0x00000000, 0xc0001800, 0xca0000f8, + 0x00000000, 0x00000000, 0xa60cffea, 0xc6f00500, 0xc6b0c400, 0xcf0000f8, 0x00000000, 0xc121fffe, + 0x5911fe14, 0x14100000, 0x8000c9c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000c960, + 0xdcbc00f9, 0x5ffc0000, 0x84000052, 0xc3800002, 0xdb8800f9, 0x5ffc0004, 0x8400c292, 0xc3800000, + 0xdb8800f9, 0xc3ce0002, 0xc0000800, 0xcfc0e700, 0xc3e1fffe, 0x597dfffe, 0x593dfe14, 0x94000001, + 0x00000000, 0x00000000, 0x00000000, 0xc000487c, 0xc80400f8, 0x00000000, 0x00000000, 0x40080000, + 0xcbc000f8, 0xc43800f8, 0x00000000, 0xc000480e, 0xca0000f8, 0xc0004858, 0xcb4400f8, 0x00000000, + 0x00000000, 0x47610000, 0x880000b0, 0x00000000, 0xa7c00048, 0xc0004854, 0xc1000002, 0xcd0400f8, + 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x800000d8, 0x00000000, 0xa7d20138, 0x00000000, 0xc7e14040, + 0xc2400000, 0xc6246028, 0xc200006a, 0x46250000, 0xc6240030, 0xc0000810, 0xce440030, 0x8000ff70, + 0xc2000000, 0xc0000808, 0xca040010, 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x5a200002, 0x5e600010, + 0x84000010, 0xc2000000, 0xc0000808, 0xce040010, 0xc3400000, 0x80000028, 0xc1200002, 0xc0000818, + 0xcd061000, 0x5b740002, 0xc0004858, 0xcf4400f8, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000, + 0xc11c0002, 0xc000082c, 0xcd05ce00, 0x80000600, 0x5b740002, 0xc0004858, 0xcf4400f8, 0xc78000f8, + 0xc13c0002, 0xcd03de00, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c, 0xc9840028, 0x59540002, + 0xc0004848, 0xcd4400f8, 0x58880002, 0xb4980580, 0x00000000, 0xc0800000, 0x80000568, 0xc000487c, + 0xc80400f8, 0x00000000, 0x00000000, 0x40080000, 0xcbc000f8, 0xc42800f8, 0x00000000, 0xa7c00130, + 0xc000484c, 0xca0400f8, 0xc2400000, 0xc0001aec, 0xca440018, 0x5a200002, 0xc000484c, 0xce0400f8, + 0xb624008a, 0xc68000f8, 0xc13c0002, 0xcd03de00, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c, + 0xc9840028, 0x59540002, 0xc0004848, 0xcd4400f8, 0x58880002, 0xb4980470, 0x00000000, 0xc0800000, + 0x80000458, 0xc0004854, 0xc1000004, 0xcd0400f8, 0xc0000820, 0xc2000002, 0xce0400f8, 0xc2000000, + 0xc000484c, 0xce0400f8, 0xc0004858, 0xce0400f8, 0x8000ff28, 0xc0004854, 0xc1000000, 0xcd0400f8, + 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc1200000, + 0xc0000818, 0xcd061000, 0xc11c0002, 0xc000082c, 0xcd05ce00, 0xc2000000, 0xc000484c, 0xce0400f8, + 0x80000358, 0xc0001ac0, 0xcb8400f8, 0xc000487c, 0xc80400f8, 0x00000000, 0x00000000, 0x40080000, + 0xcbc000f8, 0xc42800f8, 0x00000000, 0x00000000, 0xc68000f8, 0xc13c0000, 0xcd03de00, 0xa780024a, + 0x00000000, 0x00000000, 0xa7c0020a, 0x00000000, 0xc0001b00, 0xc2060006, 0xce046308, 0xa7e801c2, + 0x00000000, 0xc0004850, 0xca0400f8, 0xc2400000, 0xc0001aec, 0xca448018, 0x5a200002, 0xc0004850, + 0xce0400f8, 0xb62400aa, 0x00000000, 0xc68000f8, 0xc13c0002, 0xcd03de00, 0xc0001acc, 0xc2000002, + 0xce040000, 0xc0004848, 0xc94400f8, 0xc1800000, 0xc000082c, 0xc9840028, 0x59540002, 0xc0004848, + 0xcd4400f8, 0x58880002, 0xb49801c8, 0x00000000, 0xc0800000, 0x800001b0, 0xc0004854, 0xc1000000, + 0xcd0400f8, 0xc11c0000, 0xc000082c, 0xcd05ce00, 0x99005590, 0xc0004848, 0xc94400f8, 0xc1800000, + 0xc2000000, 0xc0000820, 0xce0400f8, 0xc1200000, 0xc0000818, 0xcd061000, 0xc11c0002, 0xc000082c, + 0xcd05ce00, 0xc0004850, 0xce0400f8, 0xc2000002, 0xc0001acc, 0xce040008, 0x800000e8, 0xc2000002, + 0xc0004850, 0xce0400f8, 0x8000fe88, 0xc2000000, 0xc0004850, 0xce0400f8, 0xa7e60032, 0x00000000, + 0xc2000002, 0xc0001b00, 0xce040000, 0x8000fe70, 0x00000000, 0xa7860052, 0x00000000, 0xc68000f8, + 0xc13c0002, 0xcd03de00, 0xc2020002, 0xc7e2a540, 0xc0001b00, 0xce0400f8, 0x8000fe18, 0xc2040002, + 0xc0001b00, 0xce044200, 0x8000fdf8, 0xc2c80002, 0x6ac56000, 0xdacc00f8, 0xc0004854, 0xcb4400f8, + 0xc0004848, 0xcb8400f8, 0xc0000838, 0xc3c00000, 0xcbc40028, 0x5ef40004, 0x84000022, 0xc3000000, + 0xc0001acc, 0xcf042100, 0x47f98000, 0x8400002a, 0x47f98000, 0x88000030, 0xc1006e8c, 0x8000b6c8, + 0xc0004840, 0xcc8400f8, 0x8000f6b0, 0xc0001ac0, 0xcac400f8, 0xc0004854, 0xcb4400f8, 0xa6c0fbd2, + 0x00000000, 0x5ef40000, 0x8400f70a, 0x5ef40002, 0x8400f99a, 0x5ef40004, 0x8400fb9a, 0xc1006ce8, + 0x8000b640, 0x00000000, 0xc0800000, 0xdf4b0038, 0xc0004900, 0xcb8000f8, 0xc2000000, 0xc000490a, + 0xa78000d0, 0xcbc000f8, 0xc1000000, 0xd90000f9, 0xc1000002, 0xd90c00f8, 0x6ff46000, 0x477da000, + 0x5b744c80, 0xc2400000, 0x58340004, 0xca400078, 0xc0004900, 0xce000000, 0x5a640002, 0x58340004, + 0xc6500078, 0xcd000078, 0xc0004914, 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000, 0xce4000f8, + 0xc0000408, 0xce0000f8, 0xa78200d8, 0xc0004908, 0xcbc000f8, 0xc1000000, 0xd90000f9, 0xc1000002, + 0xd90c00f8, 0x6ff4a000, 0x6fd44000, 0x4755a000, 0x477da000, 0x5b747000, 0xc2800000, 0x58340006, + 0xca800078, 0xc2000000, 0xc0004900, 0xce002100, 0x5ea80002, 0x58340006, 0xc6900078, 0xcd000078, + 0x5a7c0020, 0xc2000002, 0x6a250000, 0xc0000408, 0xce0000f8, 0xdca800f9, 0x5ea80000, 0x8400b4b0, + 0x00000000, 0xa4800230, 0x00000000, 0xc3c00000, 0xc000140e, 0xcbc00018, 0xc3400000, 0xc2400000, + 0x6ff86000, 0x47bdc000, 0x5bb84c80, 0x58380008, 0xcb400078, 0x58380006, 0xca400078, 0x5f740002, + 0x58380008, 0xc7500078, 0xcd000078, 0xc2000000, 0x58380004, 0xca020078, 0xc3000000, 0x5838000c, + 0xcb000020, 0x5a640002, 0x46610000, 0x84000010, 0xc2400000, 0x58380006, 0xc6500078, 0xcd000078, + 0xc2000000, 0x5838000a, 0xca020078, 0x5b300002, 0x5838000c, 0xc7100020, 0xcd000020, 0xc2420020, + 0x5a200004, 0x46252000, 0x84000010, 0xc2000000, 0x5838000a, 0xc6101078, 0xcd021078, 0xc0004966, + 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000, 0xce4000f8, 0x5f740000, 0x84000040, 0xc0004912, + 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0x5f300020, 0x84000040, + 0xc0004924, 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0xa4820070, + 0xc2400000, 0xc000140e, 0xca408018, 0xc2000002, 0xc0004900, 0xce000000, 0xc000490a, 0xce4000f8, + 0xc1000000, 0xd90000f9, 0xd8400078, 0xc1000004, 0xd90000f9, 0xa4840270, 0x00000000, 0xc3c00000, + 0xc000140e, 0xcbc10018, 0xc2800000, 0xc2000000, 0x6ff8a000, 0x6fd44000, 0x4795c000, 0x47bdc000, + 0x5bb87000, 0x5838002e, 0xca800078, 0x58380006, 0xca020078, 0xc3400000, 0x5838002e, 0xcb420078, + 0x5aa80002, 0x46a10000, 0x84000010, 0xc2800000, 0x5838002e, 0xc6900078, 0xcd000078, 0x5f740002, + 0x5838002e, 0xc7501078, 0xcd021078, 0xc0004968, 0xca4000f8, 0xc2000002, 0x6a3d0000, 0x72612000, + 0xce4000f8, 0xc000492a, 0xca8000f8, 0x5e740000, 0x84000040, 0xc0004910, 0xca0000f8, 0xc2c00002, + 0x6afd6000, 0x7ec16000, 0x762d0000, 0xce0000f8, 0x6abd4010, 0xa68000ba, 0x00000000, 0x58380032, + 0xca0000f8, 0x58000002, 0xca4000f8, 0x5838000c, 0x00000000, 0xce0000f9, 0xce4000f8, 0xc000492a, + 0xca0000f8, 0xc2c00002, 0x6afd6000, 0x722d0000, 0xce0000f8, 0xc000492c, 0xca0000f8, 0xc2c00002, + 0x6afd6000, 0x722d0000, 0xce0000f8, 0x80000040, 0xc000492c, 0xca0000f8, 0xc2c00002, 0x6afd6000, + 0x7ec16000, 0x762d0000, 0xce0000f8, 0xa4880148, 0xc2c00000, 0xc000140e, 0xcac20018, 0xc000490e, + 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x7e010000, 0x76612000, 0xce4000f8, 0xc000496a, 0xca4000f8, + 0xc2000002, 0x6a2d0000, 0x72612000, 0xce4000f8, 0x6ef0a000, 0x6ed44000, 0x47158000, 0x472d8000, + 0x5b307000, 0x58300000, 0xca0000f8, 0x00000000, 0xc2400002, 0x76612000, 0x84000072, 0x58300000, + 0xca4000f8, 0xc2800000, 0x00000000, 0xc6684018, 0xc24c0002, 0xc6a40018, 0xc624c400, 0x58300010, + 0xca400500, 0x00000000, 0xc0001800, 0xce4000f8, 0xa4860070, 0xc2400000, 0xc000140e, 0xca418018, + 0xc2020002, 0xc0004900, 0xce002100, 0xc0004908, 0xce4000f8, 0xc1000000, 0xd90000f9, 0xd8400078, + 0xc1000004, 0xd90000f9, 0xc0001408, 0xcc8000f8, 0xc10e0002, 0xd90c00f8, 0x8000edb0, 0xdfbc00f9, + 0xc000496e, 0x99006298, 0xc94000f8, 0xc7d800f8, 0x00000000, 0xc57000f8, 0x5ef00020, 0x88000148, + 0x6f346000, 0x4771a000, 0x5b744c80, 0x58340008, 0xc2400000, 0xca400078, 0x00000000, 0xc2000000, + 0x5a640002, 0xce400078, 0x58340004, 0xca000078, 0x00000000, 0x00000000, 0x5e200002, 0xce000078, + 0xc0004912, 0xca8000f8, 0xc2400002, 0x6a712000, 0x72a54000, 0xce8000f8, 0x5e200000, 0x84000052, + 0xc000480a, 0xca0000f8, 0xc0000408, 0xca8000f8, 0x76250000, 0x00000000, 0x72a14000, 0xce8000f8, + 0x80000038, 0xc0004914, 0xca0000f8, 0x7e412000, 0x00000000, 0x76250000, 0xce0000f8, 0x800000d0, + 0x6ef4a000, 0x6ed44000, 0x4755a000, 0x476da000, 0x5b747000, 0x5834002e, 0xc2400000, 0xca420078, + 0x00000000, 0xc2000000, 0x5a640002, 0xc6501078, 0xcd021078, 0x58340006, 0xca000078, 0x00000000, + 0x00000000, 0x5a200002, 0xce000078, 0xc0004910, 0xca4000f8, 0xc2000002, 0x6a2d0000, 0x72612000, + 0xce4000f8, 0xc2000002, 0x6a310000, 0xc000042a, 0xce0000f8, 0xc1040002, 0xd90c00f8, 0x00000000, + 0x8000eb20, 0x00000000, 0xc4980928, 0x9d000000, 0xc5580028, 0xc0000838, 0xcd8400f8, 0xc1440200, + 0xc1c03800, 0xc55c1070, 0xc000100e, 0x9d000000, 0xcd8000f8, 0xc000100c, 0xcdc000f8, 0xc0004862, + 0xc9c000f8, 0x00000000, 0x00000000, 0xd9d800f9, 0xc0007800, 0x401c0000, 0x5dc07a00, 0x88000012, + 0x5c000200, 0xcd8000f8, 0xc1f0000a, 0x715ca000, 0xdd9800f8, 0xdd9c00f9, 0x41d8e000, 0xc5d40260, + 0xc0001010, 0xcd4000f8, 0x6c9c8000, 0x45c8e000, 0x45c8e000, 0x59dc0004, 0xc1601260, 0xc5d40260, + 0x9d000000, 0xc0001012, 0xcd4000f8, 0x00000000, 0x00000000, 0xd95800f8, 0x6d586000, 0x4594c000, + 0x59984c80, 0xd99800f9, 0x5818000a, 0xc1800000, 0xc9800078, 0xc0006e00, 0x6d5ca000, 0x401c0000, + 0x40180000, 0xc94000f8, 0x58000002, 0x00000000, 0xc9c000f8, 0xc0004930, 0xcd4000f8, 0xc0004932, + 0xcdc000f8, 0x59980004, 0xc1c20020, 0xb59c0018, 0x00000000, 0xc1800000, 0xdd9c00f9, 0x581c000a, + 0xcd800078, 0x581c000c, 0xc1800000, 0xc9800020, 0xc1c00002, 0xdd9400f8, 0x69d4e000, 0x5d980002, + 0xcd800020, 0xc0004924, 0xc98000f8, 0x00000000, 0x9d000000, 0x00000000, 0x719cc000, 0xcd8000f8, + 0xc000492a, 0xc94000f8, 0xc1c00002, 0x69d8e000, 0x7dc0c000, 0x7558a000, 0xcd4000f8, 0xc000492c, + 0xc94000f8, 0xdd8000f9, 0x58000032, 0x755ca000, 0x84000090, 0xc94000f9, 0xc98000f8, 0xdd8000f9, + 0x5800000c, 0x00000000, 0xcd4000f9, 0xcd8000f8, 0xc000492c, 0xc94000f8, 0xc000492a, 0xc98000f8, + 0x715ca000, 0xc000492c, 0xcd4000f8, 0x719cc000, 0xc000492a, 0xcd8000f8, 0x9d000000, 0x00000000, + 0x00000000, 0x00000000, 0xc0004862, 0xc98000f8, 0x00000000, 0xc1c00200, 0x4194c000, 0x459ce000, + 0x88000012, 0xc5d800f8, 0xc0004862, 0xcd8000f8, 0xc0001406, 0xc98000f8, 0xc1c00002, 0x9d000000, + 0xc5d80a00, 0xc5581048, 0xcd8000f8, 0xc0004930, 0xc98000f8, 0xc0004932, 0xc9c000f8, 0xc140000e, + 0xc5581c18, 0xdd9400f8, 0xc0007800, 0x40140000, 0x5d407a00, 0x88000012, 0x5c000200, 0xcd8000f8, + 0x58000002, 0x5d407a00, 0x88000012, 0x5c000200, 0xcdc000f8, 0xdd5400f8, 0xc1c00000, 0x58140006, + 0xc9c20078, 0xc1800000, 0x58140000, 0xc98000d8, 0x6ddc2000, 0xc000491e, 0x41d8e000, 0xcdc000f8, + 0xdd9800f8, 0xc1c00022, 0xc5d80d70, 0xdd9400f9, 0xc5581c18, 0xc000491c, 0xcd8000f8, 0xdd5400f8, + 0xc1c00000, 0x58140006, 0xc9c20078, 0xc1800000, 0x58140004, 0xc9820078, 0x00000000, 0x59dc0002, + 0x45d8c000, 0x84000010, 0xc1c00000, 0x9d000000, 0x58140006, 0xc5d81078, 0xcd821078, 0xc0004860, + 0xc94000f8, 0xc1820080, 0xc1d00002, 0x58147700, 0xd58000f8, 0x58000002, 0xd58000f9, 0x59540004, + 0xb5580018, 0xc0004860, 0xc1400000, 0xcd4000f8, 0xdd9800f9, 0x9d000000, 0xdd9400f8, 0xc0001404, + 0xcdc10800, 0xc1c00000, 0xc1800200, 0x5d980004, 0xdf5d0048, 0x459ca000, 0x8800fff2, 0xdd8000f9, + 0x5800000c, 0x00000000, 0xc94000f9, 0xc98000f8, 0xc1c00002, 0xc5d43f00, 0xc5d81e00, 0xc0004862, + 0xc9c000f8, 0x00000000, 0x00000000, 0x581c7800, 0x5dc07a00, 0x88000012, 0x5c000200, 0xcd4000f8, + 0x58000002, 0x5dc07a00, 0x88000012, 0x5c000200, 0xcd8000f8, 0xc0004862, 0xc9c000f8, 0x00000000, + 0xc15004c0, 0xc5d40060, 0xdd9c00f8, 0xc5d41c18, 0xc1c00000, 0xdd8000f9, 0x58000030, 0xc9c00078, + 0xdd8000f9, 0x58000002, 0xc98000f8, 0x6ddc2000, 0xc000491c, 0x41d8e000, 0xcd4000f9, 0xcdc000f8, + 0xdd9400f9, 0xc1c00000, 0x58140030, 0xc9c00078, 0xc1800000, 0x58140006, 0xc9820078, 0x00000000, + 0x59dc0002, 0x45d8c000, 0x84000010, 0xc1c00000, 0x9d000000, 0x58140030, 0xc5d80078, 0xcd800078, + 0xc1c00000, 0xdf5c0038, 0x5ddc0080, 0x8400ffea, 0x00000000, 0x9d000000, 0x00000000, 0x00000000, + 0x00000000, 0xc160fffe, 0xc0000a10, 0xc9440060, 0xc1a0fffe, 0x59983008, 0xc000100c, 0xcd4000f8, + 0xc000100e, 0xcd8000f8, 0xc0004964, 0xc98000f8, 0x00000000, 0xc170000a, 0x7158a000, 0x6c988000, + 0x4588c000, 0x4588c000, 0x59980004, 0xc5940270, 0xc0001010, 0xcd4000f8, 0xc0004946, 0xc94000f8, + 0x00000000, 0x00000000, 0x6d58a000, 0x6d5c4000, 0x459cc000, 0x4594c000, 0xc000494a, 0xc94000f8, + 0xc0004948, 0xc9c000f8, 0x4194c000, 0xc1400012, 0xc55c1818, 0x9d000000, 0xc59c0268, 0xc0001012, + 0xcdc000f8, 0xc1400000, 0x58000012, 0xc9410038, 0xc0004950, 0xc9c000f8, 0xc55800f8, 0xc5940838, + 0xc5581078, 0xd99400f8, 0xc000493c, 0xc94000f8, 0xc0004954, 0xc98000f8, 0x59dc00a8, 0x45d4e000, + 0x41d8e000, 0x5d5c0030, 0x88000010, 0xc1c00030, 0xc1800000, 0xc5d84028, 0xc1400000, 0xc5d40008, + 0x5dd40002, 0x84000072, 0x5dd40004, 0x8400009a, 0x5dd40006, 0x840000c2, 0x5dd80026, 0x840000ea, + 0xdd5400f8, 0xdd8000f9, 0x58000008, 0x40180000, 0xcd4000f8, 0x59980002, 0x8000ffc0, 0xdd5400f8, + 0xdd8000f9, 0x58000008, 0x40180000, 0xcd4000b8, 0x59980002, 0x8000ff88, 0xdd5400f8, 0xdd8000f9, + 0x58000008, 0x40180000, 0xcd400078, 0x59980002, 0x8000ff50, 0xdd5400f8, 0xdd8000f9, 0x58000008, + 0x40180000, 0xcd400038, 0x59980002, 0x8000ff18, 0x00000000, 0x9d000000, 0x00000000, 0x00000000, + 0x00000000, 0x58000012, 0xc94000f8, 0xc0004954, 0xc9c000f8, 0xc0004950, 0xc9400078, 0xdd8000f9, + 0x58000028, 0x5d9c0000, 0x84000052, 0x5d9c0002, 0x84000052, 0x5d9c0004, 0x8400006a, 0xc55b0038, + 0xc55c08b8, 0xcd800039, 0xcdc108b8, 0x80000060, 0xcd4000f8, 0x80000050, 0xc55900b8, 0xc55c1838, + 0xcd8000b9, 0xcdc31838, 0x80000028, 0xc55a0078, 0xc55c1078, 0xcd800079, 0xcdc21078, 0x9d000000, + 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6994e018, 0x61c0c008, 0x4194a000, 0x5d940040, + 0x88000012, 0xc59400f8, 0x9d000000, 0xcd4000f8, 0x00000000, 0x00000000, 0x9d000000, 0x4158a000, + 0xcd4000f8, 0x00000000, +}; + +static unsigned int firmware_binary_data[] = { +}; + + +#endif // IFXMIPS_ATM_FW_AR9_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h new file mode 100644 index 0000000000..0fc4789356 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_ar9_retx.h @@ -0,0 +1,611 @@ +#ifndef IFXMIPS_ATM_FW_AR9_H
+#define IFXMIPS_ATM_FW_AR9_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_ar9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 22 OCT 2007
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 22 OCT 2007 Xu Liang Initiate Version, v00.01
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 15
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004B8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFE0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C00F8, 0xC2000002, 0xDA0800F9, 0xC0001B50, 0x8C100000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC2000000, 0xDA0800F9, 0x80006030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80006008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1001DA6, 0x8D3C0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005F08, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC0004840, 0xC88400F8, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC0004840, 0xC88400F8, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC800F9, 0xC10C0002, 0xD90C00F8, 0x8000FEE0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C00F8, 0xC0004808, 0xC84000F8, 0xC2001B4C, 0x8E100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3E0A252, 0x5BFC001E, 0xC0004002, 0xCFC000F8, 0xC3C00000,
+ 0xDBC800F9, 0xC1400008, 0xC1900000, 0x71588000, 0x14100100, 0xC140000A, 0xC1900002, 0x71588000,
+ 0x14100100, 0xC140000C, 0xC1900004, 0x71588000, 0x14100100, 0xC1400004, 0xC1900006, 0x71588000,
+ 0x14100100, 0xC1400006, 0xC1900008, 0x71588000, 0x14100100, 0xC140000E, 0xC190000A, 0x71588000,
+ 0x14100100, 0xC1400000, 0xC190000C, 0x71588000, 0x14100100, 0xC1400002, 0xC190000E, 0x71588000,
+ 0x14100100, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC11C0002, 0xC000082C, 0xCD05CE00,
+ 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC0000824, 0x00000000, 0xCBC000F9, 0xCB8000F9,
+ 0xCB4000F9, 0xCB0000F8, 0xC0004878, 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F9, 0x5B744000,
+ 0xCF4000F9, 0x5B304000, 0xCF0000F8, 0xC0000A10, 0x00000000, 0xCBC000F9, 0xCB8000F8, 0xC0004874,
+ 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F8, 0xC30001FE, 0xC000140A, 0xCF0000F8, 0xC3000000,
+ 0x7F018000, 0xC000042E, 0xCF0000F8, 0xC000040E, 0xCF0000F8, 0xC3C1FFFE, 0xC000490E, 0xCFC00078,
+ 0xC000492C, 0xCFC00078, 0xC0004924, 0xCFC00038, 0xC0004912, 0xCFC00038, 0xC0004966, 0xCFC00038,
+ 0xC0004968, 0xCFC00078, 0xC000496A, 0xCFC00078, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFC8,
+ 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47BDC000, 0x5BB84C80, 0xC3400000, 0x58380004,
+ 0xCB420078, 0x00000000, 0x58380008, 0xCF400078, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0xC3C00000,
+ 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x58380008, 0xCF408418, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFB0, 0x00000000,
+ 0x00000000, 0xC0004816, 0xC3C00000, 0xCBC00078, 0x00000000, 0x00000000, 0xC1000000, 0xD90400F9,
+ 0xDBC40078, 0xC1000006, 0xD90400F9, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0xC3C00000,
+ 0xDCFC2000, 0x5FFC0002, 0x00000000, 0x98C08D62, 0xC0004730, 0xC94000F8, 0xC0004732, 0xC0001AF2,
+ 0xCBC000F8, 0x00000000, 0x00000000, 0xA7C20470, 0xC000474A, 0xCA8000F8, 0x00000000, 0x00000000,
+ 0x5D280000, 0x8400FFE0, 0x00000000, 0xC121FFFE, 0x5911FEF4, 0x14100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2802000, 0x6EA8E010, 0xC0004200, 0xC2400000, 0x7E410000, 0xC1000000, 0xCE4000F9, 0xCE4000F9,
+ 0xCE4000F9, 0xCE4000F9, 0x5EA80002, 0x8400FFD8, 0xC0004300, 0xC2800200, 0x6EA84010, 0xCE4000F9,
+ 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0xCE4000F9, 0xCE0000F9, 0x5EA80002,
+ 0x8400FFB8, 0xC0004700, 0xC2800200, 0x6EA8E010, 0xCE4000F9, 0xCE4000F9, 0xCE4000F9, 0xCE4000F9,
+ 0x5EA80002, 0x8400FFD8, 0xC0004740, 0xCE4000F8, 0xC0004742, 0xC1000200, 0x5D100002, 0xCD0000F8,
+ 0xC0004744, 0xCE4000F8, 0xC0004746, 0xCE4000F8, 0xC0004748, 0xCE4000F8, 0xC000474A, 0xCE4000F8,
+ 0xC000474C, 0xC1000002, 0xCD0000F8, 0xC000474E, 0xCE4000F8, 0xC0004750, 0xCE4000F8, 0xC0004752,
+ 0xCE4000F8, 0xC0004754, 0xCE4000F8, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD05CE00, 0xC0000838,
+ 0xCE4000F8, 0xC0000818, 0xCE4000F8, 0xC0000820, 0xCE4000F8, 0xC2804840, 0xC240485A, 0x98C086B0,
+ 0xC68000F8, 0xC65400F8, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD05CE00, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0xC0000A10, 0xCB8000F8, 0xC0000A12, 0xCB4000F8, 0xC0000A14, 0xCB0000F8,
+ 0xC0000A16, 0xCAC000F8, 0xC0000040, 0xC2800000, 0xCE800000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC2800002,
+ 0xCE800000, 0xC0000A10, 0xCF8000F8, 0xC0000A12, 0xCF4000F8, 0xC0000A14, 0xCF0000F8, 0xC0000A16,
+ 0xCEC000F8, 0xC1000000, 0xC00048A0, 0xCD0000F8, 0xC00048A2, 0xCD0000F8, 0xC0001AF2, 0xC1000000,
+ 0xCD002100, 0x80001038, 0x00000000, 0xC3C00000, 0xDCFC2000, 0x5FFC0002, 0x00000000, 0x98C08D62,
+ 0xC0004730, 0xC94000F8, 0xC0004732, 0x800033D8, 0x00000000, 0xC3C00000, 0xDCFC2000, 0x5FFC0002,
+ 0x00000000, 0x98C08D62, 0xC0004730, 0xC94000F8, 0xC0004732, 0xC0004810, 0xC90000F8, 0xC000474A,
+ 0xC94000F8, 0xA50007E8, 0x00000000, 0x5D140002, 0x840007D2, 0xC1000000, 0xC000484A, 0xC90000F8,
+ 0xC0004740, 0xC84000F8, 0x5D100000, 0x84000798, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FEF4,
+ 0x14100000, 0xC0004744, 0xC88000F8, 0xC0001AF0, 0xC3000000, 0x58000002, 0xCB010038, 0x6C7C2000,
+ 0x5BFC4300, 0x98C08A88, 0xC1400000, 0xC4540020, 0x6C40A010, 0x5D240002, 0x8400021A, 0x00000000,
+ 0xC0004742, 0xCA8000F8, 0x00000000, 0x00000000, 0x59280002, 0x6D130000, 0x6D130010, 0x45048000,
+ 0x84000692, 0x00000000, 0x98C08870, 0xC45400F8, 0xC69800F8, 0xC241FFFE, 0xC67400F8, 0x5D35FFFE,
+ 0x84000652, 0x47448000, 0x84000642, 0xC1000000, 0x6F502000, 0xC0004300, 0x40100000, 0xC1400000,
+ 0x58000000, 0xC9410038, 0xC1800000, 0xC0004814, 0xC9820038, 0x4714A000, 0xC10001FE, 0x4150A004,
+ 0x45588000, 0x880005CA, 0x4744C000, 0xC1000200, 0x4190C004, 0xC000473E, 0xC90000F8, 0x00000000,
+ 0x00000000, 0x41188000, 0xCD0000F8, 0xC000471C, 0xC90000F8, 0x00000000, 0x00000000, 0x41188000,
+ 0xCD0000F8, 0x98C087E8, 0xC45400F8, 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010,
+ 0x44748000, 0x8400FFC0, 0xC74400F8, 0xC0004740, 0xCC4000F8, 0xC0800000, 0xC0004744, 0xCC8000F8,
+ 0x800004D0, 0xC1000000, 0x583C0000, 0xC9000038, 0x00000000, 0x00000000, 0x44908000, 0x88000280,
+ 0xC1400000, 0x583C0000, 0xC9410038, 0xC1800000, 0xC0004814, 0xC9800038, 0x4714A000, 0xC10001FE,
+ 0x4150A004, 0x45588000, 0x88000442, 0xC3800000, 0x583C0002, 0xCB820078, 0xC1000000, 0x583C0002,
+ 0xC9000078, 0x00000000, 0x00000000, 0x47908000, 0x8400024A, 0xC0400002, 0xC0800000, 0xC3C00000,
+ 0xC000481A, 0xC80000F8, 0x6F908000, 0x45388000, 0x45388000, 0x4011E000, 0xC000491E, 0xCFC000F8,
+ 0xC3400000, 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCAC000F8,
+ 0xC43000F8, 0x00000000, 0xC7340060, 0xC1000002, 0xC5341B00, 0xC100001C, 0xC5341048, 0xC100000C,
+ 0xC5340D10, 0xC000491C, 0xCF4000F8, 0xC3000000, 0xDF700038, 0x5D300080, 0x8800FFE8, 0xC000474A,
+ 0xC1000002, 0xCD0000F8, 0xC000491C, 0xCB4000F8, 0xC000491E, 0xCBC000F8, 0x99007F18, 0xDB5800F8,
+ 0xDBD800F9, 0x00000000, 0xC1400000, 0xC794A030, 0xC1800000, 0xC7980020, 0x58144200, 0xC9C000F8,
+ 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x80000228, 0x00000000, 0xC1000000,
+ 0x583C0000, 0xC903E000, 0x00000000, 0x00000000, 0x5D100000, 0x84000042, 0xC0004734, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800000C0, 0xC1400000, 0x583C0000, 0xC9410038,
+ 0xC1800000, 0xC0004814, 0xC9820038, 0x4714A000, 0xC10001FE, 0x4150A004, 0x45588000, 0x8800015A,
+ 0xC000473E, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC000471C, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC3800000, 0x583C0002, 0xCB820078, 0x00000000,
+ 0x00000000, 0x5D39FFFE, 0x84000062, 0xC1400000, 0xC794A030, 0xC1800000, 0xC7980020, 0x58144200,
+ 0xC9C000F8, 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x98C087E8, 0xC45400F8,
+ 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010, 0xC0004740, 0xCC4000F8, 0xC0800000,
+ 0xC0004744, 0xCC8000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000F288, 0x00000000,
+ 0x00000000, 0x98C086F0, 0xC0004748, 0xC98000F8, 0xC2000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC1400000, 0xC7D4A030, 0xC1800000, 0xC7D80020, 0x58144200,
+ 0xC9C000F8, 0xC1210000, 0x69188010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C087E8, 0xC7D400F8, 0x6FD8A010, 0xC0004700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C08870, 0xC7D400F8, 0xC79800F8, 0xC241FFFE, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08A88, 0xC1400000, 0xC7D40020, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AB8, 0xC1400000, 0xC7D40020, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AF0, 0xC7D400F8, 0xC0004740, 0xC9C000F8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08BE0, 0xC7D400F8, 0xC0004742, 0xC98000F8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004958, 0xC84000F8, 0x00000000, 0xC3C00002,
+ 0x787C2000, 0xCC4000F8, 0xC0004848, 0xCB8400F8, 0xC000495C, 0xCAC400F8, 0xC0004844, 0xC88400F8,
+ 0x47AD0000, 0x8400F492, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCA0000F8,
+ 0xC0001624, 0xCB0400F8, 0xA63C007A, 0x00000000, 0x00000000, 0xA71EF432, 0x00000000, 0xC0000824,
+ 0xCA8400F8, 0x6CA08000, 0x6CA42000, 0x46250000, 0x42290000, 0xC35E0002, 0xC6340060, 0xC0001624,
+ 0xCF440078, 0xC2000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC0004844, 0xC88400F8, 0xC000082C, 0xCA040038, 0x00000000, 0x00000000, 0x58880002,
+ 0xB6080018, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840038, 0x5AEC0002, 0xC000495C, 0xCEC400F8,
+ 0x5E6C0006, 0x84000060, 0xC0004848, 0xCB8400F8, 0xC0000838, 0xC2500002, 0xCE450800, 0x5FB80002,
+ 0xC0004848, 0xCF8400F8, 0x5EEC0002, 0xC000495C, 0xCEC400F8, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0x8000F290, 0xC000495A, 0xC84000F8, 0x00000000, 0xC3C00002, 0x787C2000, 0xCC4000F8,
+ 0xC0004960, 0xCAC400F8, 0x00000000, 0x00000000, 0x5EEC0000, 0x8400010A, 0x00000000, 0xB6FC0050,
+ 0xC0001600, 0xCA0400F8, 0x00000000, 0x00000000, 0xA61E00D2, 0x6FE90000, 0xC0000A28, 0xCE850800,
+ 0xC2C00000, 0xC2800004, 0xB6E800A0, 0xC0001604, 0xCA8400F8, 0xC0004960, 0xCEC400F8, 0xA69EFCAA,
+ 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE850800, 0xC2C00002, 0xC0001600, 0xCA0400F8, 0x00000000,
+ 0x00000000, 0xA61E002A, 0x6FE90000, 0xC0000A28, 0xCE850800, 0xC2C00000, 0xC0001604, 0xCA8400F8,
+ 0xC0004960, 0xCEC400F8, 0xA69EFC12, 0xC2400000, 0xC0000A14, 0xCA440028, 0x00000000, 0x00000000,
+ 0x466D2000, 0xA4400020, 0xC2800000, 0xDFEB0029, 0x80000010, 0xDFEA0029, 0xB668EC0A, 0x00000000,
+ 0xC00048A0, 0xCB0400F8, 0xC0000A10, 0xCA8400F8, 0x6F208000, 0x6F242000, 0x46250000, 0x42A10000,
+ 0xC2400000, 0xC0000A14, 0xCA440028, 0xC35E0002, 0xC6340060, 0xC0001604, 0xCF440078, 0x5B300002,
+ 0xB6700018, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF0400F8, 0xC0004960, 0xCEC400F8, 0x8000F030,
+ 0xC0004918, 0xD28000F8, 0xC2000000, 0xDF600038, 0x5E600080, 0x840002A2, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000480A, 0xCA0000F8,
+ 0xC0004912, 0xCA4000F8, 0xC0004924, 0xCA8000F8, 0xC0004966, 0xCAC000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x76250000, 0x76290000, 0x762D0000, 0x840001E2, 0xC0004918, 0xCA4000F8,
+ 0xC28001FE, 0x76290000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x8400001A, 0x6AA54000, 0x80000010,
+ 0xC62800F8, 0x62818008, 0xC0004918, 0xCF0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC0004966, 0xCA4000F8, 0xC2000002, 0x6A310000, 0x7E010000,
+ 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6F346000, 0x4771A000,
+ 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800078, 0xC2C00000, 0x58340000, 0xCAC000D8, 0xC2400000,
+ 0x5834000A, 0xCA420078, 0x6EA82000, 0x42E9E000, 0x6F2CA000, 0x42E56000, 0x5AEC2E00, 0xC3990040,
+ 0xC7381C18, 0xC6F80060, 0x99007F18, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xDEA000F8, 0x46310000,
+ 0x8400FD50, 0xC0004958, 0xC84000F8, 0x00000000, 0xC1000002, 0x78502000, 0xCC4000F8, 0xC0004848,
+ 0xCBC400F8, 0xC0004844, 0xC88400F8, 0x5FFC0000, 0x8400ECBA, 0xC0004740, 0xCB0000F8, 0xC0004744,
+ 0xCAC000F8, 0x6F282000, 0x5AA84300, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000,
+ 0xCA4000F8, 0xC40000F8, 0x00000000, 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000,
+ 0x40100000, 0xC90000F8, 0xC43400F8, 0x00000000, 0x5C440000, 0x840000A2, 0x00000000, 0xC00047D2,
+ 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x58340002, 0xC9000078, 0x00000000,
+ 0x00000000, 0x58280002, 0x6D120000, 0xCD021078, 0x5AEC0002, 0xC0004744, 0xCEC000F8, 0x80000630,
+ 0x00000000, 0xC00047C0, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xA67C0048,
+ 0xC00047C2, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80001E18, 0x00000000,
+ 0xA6600042, 0xC00047C4, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000570,
+ 0xC00047C6, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC3C00000, 0xC67D0038,
+ 0xC3800000, 0xC6780038, 0x47F08000, 0x840000A8, 0x47AC8000, 0x84000098, 0xC1000000, 0xC0004814,
+ 0xC9000038, 0x00000000, 0x00000000, 0x5D100000, 0x840000F0, 0x5AEC0002, 0xC0004744, 0xCEC000F8,
+ 0xC00047CA, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000478, 0x00000000,
+ 0x98C08AF0, 0xC7D400F8, 0xC0004740, 0xC9C000F8, 0x5D240000, 0x8400006A, 0x00000000, 0x98C087E8,
+ 0xC7D400F8, 0x6FD8A010, 0xC0004700, 0xC00047C8, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0x80001C40, 0xC00047CC, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x6FE82000, 0x5AA84300, 0x5D380000, 0x840000A0, 0x00000000, 0x98C086F0, 0xC0004748, 0xC98000F8,
+ 0xC2000000, 0x58280002, 0x6E520000, 0xCD021078, 0x58280002, 0xCE400078, 0x5D25FFFE, 0x84000040,
+ 0xC00047D0, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800002D0, 0xC3000000,
+ 0x58280002, 0xCB000078, 0x00000000, 0x00000000, 0x5D31FFFE, 0x84000048, 0xC00047D0, 0xC90000F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000260, 0x00000000, 0x98C086F0, 0xC0004748,
+ 0xC98000F8, 0xC2000000, 0x58340002, 0xC6500078, 0xC7D01038, 0xC7901838, 0xCD0000F8, 0x58280002,
+ 0xCE400078, 0xC3C00200, 0x5FFC001C, 0xC3800000, 0xDF790048, 0x00000000, 0x00000000, 0x47F88000,
+ 0x8800FFDA, 0xC0004862, 0xCBC000F8, 0xC0000000, 0xC76C00F8, 0x5BBC7800, 0xC280001C, 0xCA6C00F9,
+ 0x00000000, 0x00000000, 0xCE7800F9, 0xC1007A00, 0x45388000, 0xC1007800, 0xC53800FE, 0x5EA80002,
+ 0x8400FFB8, 0xC3800000, 0xC000481A, 0xC80000F8, 0x6F108000, 0x45308000, 0x45308000, 0x4011C000,
+ 0xC000491E, 0xCF8000F8, 0xC2C00000, 0xC7EC0060, 0xC100001C, 0xC52C1048, 0xC100000A, 0xC52C0D10,
+ 0xC000491C, 0xCEC000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2800000, 0xDF680038,
+ 0x5D280080, 0x8800FFE8, 0xC000491C, 0xCAC000F8, 0xC000491E, 0xCB8000F8, 0x99007F18, 0xDAD800F8,
+ 0xDB9800F9, 0x00000000, 0xC00047CE, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x00000000, 0x80001880, 0x00000000, 0x00000000, 0x00000000, 0xC0004878, 0xC80400F8, 0x6C908000,
+ 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0xC0004934, 0xCE0000F8,
+ 0xC2800002, 0xC4681C08, 0xC62821D0, 0xC6281E00, 0xC2600010, 0x5A650060, 0xC0004800, 0xCB4000F8,
+ 0xC2200400, 0x5A200020, 0xC7601040, 0xC0001220, 0xCE8000F8, 0xC0001200, 0xCE4000F8, 0xC0001202,
+ 0xCE0000F8, 0xC0001240, 0xCB4000F8, 0x00000000, 0x00000000, 0xA754FFE0, 0xC2000000, 0xC7600040,
+ 0xA7520042, 0x00000000, 0x00000000, 0x99008690, 0xC0004822, 0xC94000F8, 0xC1800002, 0x80001710,
+ 0x582040A0, 0xC2000000, 0xCA000018, 0xC2400000, 0xCA414000, 0xC2800000, 0xCA812000, 0xC2C00000,
+ 0xCAC20018, 0xC0004938, 0xCE0000F8, 0xC0004920, 0xCE4000F8, 0xC0004916, 0xCE8000F8, 0xC0004922,
+ 0xCEC000F8, 0xA6400558, 0x00000000, 0xC0004938, 0xCBC000F8, 0x00000000, 0xC3800000, 0x6FF48000,
+ 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802010, 0x00000000, 0xC2000000, 0x6FB46000,
+ 0x4779A000, 0x5B744C80, 0x5834000C, 0xCA000020, 0xC000491A, 0xCF8000F8, 0x5E200000, 0x84000482,
+ 0xC2000000, 0xDF610048, 0x5E6001E8, 0x8800FFE8, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000,
+ 0xC0001006, 0xCE0000F8, 0xC0001008, 0xCE4000F8, 0xC000100A, 0xCE8000F8, 0x99007958, 0xC1A0FFFE,
+ 0xC0000824, 0xC9840060, 0xC0004934, 0xCA4000F8, 0xC2000000, 0xC2800002, 0x99007998, 0xDA9800F8,
+ 0xC61400F8, 0xC65800F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x99007A80, 0xC000491A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0xC0004922, 0xCA001118, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE023118, 0xC0004932,
+ 0xCBC000D8, 0xC2800000, 0xC000491E, 0xCFC000F8, 0xC0004862, 0xCA800060, 0xC3A0001A, 0x5BB94000,
+ 0xC6B80060, 0xC000491C, 0xCF8000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0x00000000,
+ 0x00000000, 0x00000000, 0xA8E2FFE8, 0xC2000000, 0xC1220002, 0xD90C00F8, 0xDF600038, 0x5E600080,
+ 0x8400FFF2, 0xC000491C, 0xCA0000F8, 0xC000491E, 0xCA4000F8, 0x00000000, 0x00000000, 0x99007F18,
+ 0xDA1800F8, 0xDA5800F9, 0x00000000, 0xC2000000, 0xDF610048, 0x5E6001FE, 0x8800FFE8, 0xC0004916,
+ 0xCA8000F8, 0xC2C00000, 0xDFEC0048, 0xC2400000, 0x466D2000, 0x8400004A, 0x5EA80000, 0x8400003A,
+ 0xC2600002, 0x99008690, 0xC000482E, 0xC94000F8, 0xC1800002, 0x80000030, 0xC2600000, 0x99008690,
+ 0xC000482C, 0xC94000F8, 0xC1800002, 0xC2000068, 0xC6240078, 0xC0004930, 0xCE400080, 0xC000491A,
+ 0xC98000F8, 0xC0004862, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC4C80, 0x99007D78, 0xD95800F8,
+ 0xD99800F9, 0xD9D400F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2000000, 0xDF600038,
+ 0x5E600080, 0x8400FFEA, 0x00000000, 0xC000491C, 0xCA0000F8, 0xC000491E, 0xCA4000F8, 0x00000000,
+ 0x00000000, 0x99007F18, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0x80001160, 0x00000000, 0x99008690,
+ 0xC000482A, 0xC94000F8, 0xC1800002, 0x80001130, 0xC0004938, 0xCBC000F8, 0x00000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA600039A, 0x00000000, 0xC0004938, 0xCBC000F8, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000,
+ 0x4395C000, 0x5BB84A00, 0x58380000, 0xCB002010, 0xC2000000, 0x58380008, 0xCA020078, 0x5838000C,
+ 0xCAC000F8, 0x5838000E, 0xCA4000F8, 0xC000491A, 0xCF0000F8, 0xC0004930, 0xCEC000F8, 0xC000493C,
+ 0xCE0000F8, 0xC0004932, 0xCE4000F8, 0x5E200000, 0x84000138, 0xC2800000, 0xA6FE00D2, 0x6F206000,
+ 0x46310000, 0x5A204C80, 0x5820000C, 0xCA800020, 0x00000000, 0x00000000, 0x5EA80000, 0x8400020A,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99007A80, 0xC000491A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000,
+ 0xC0004930, 0xCAC000F8, 0xC0004932, 0xCA4000F8, 0xC7EC1118, 0xC0004930, 0xCEC000F8, 0x5838000C,
+ 0xCEC000F8, 0x58000002, 0xCE4000F8, 0xC0004934, 0xCA0000F8, 0xC2400002, 0x6E642000, 0x6E642000,
+ 0x76612000, 0x8400002A, 0xC2400002, 0x6E684000, 0x58380008, 0xCE804200, 0xA6000020, 0x6E682000,
+ 0x58380008, 0xCE802100, 0xC2400002, 0x6E642000, 0x76612000, 0x840000EA, 0x58380008, 0xCA0000F8,
+ 0xC2800000, 0xC2400000, 0xA60200C0, 0xDBA800F8, 0x6F386000, 0x47B1C000, 0x5BB84C80, 0x58380004,
+ 0xCA400078, 0x58380002, 0xCA800078, 0x00000000, 0xDEB800F8, 0x46A54000, 0x88000060, 0x00000000,
+ 0xC0004824, 0xCA0000F8, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE0000F8, 0x58380008, 0xCE400000,
+ 0x80000018, 0x00000000, 0x80000048, 0xC0004934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020CCA,
+ 0x00000000, 0x00000000, 0x80000CF8, 0xC2800000, 0xC2000200, 0xC240001A, 0xDF690048, 0x46294000,
+ 0x46A54000, 0x8800FFD2, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA8000F8, 0xC0001006,
+ 0xCE0000F8, 0xC0001008, 0xCE4000F8, 0xC000100A, 0xCE8000F8, 0x99007958, 0xC1A0FFFE, 0xC0000824,
+ 0xC9840060, 0xC2000000, 0xC0004930, 0xCA02E008, 0x58380026, 0xCA4000F8, 0x00000000, 0xC2800000,
+ 0x99007998, 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC0004934, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA6020022, 0x00000000, 0x00000000, 0x80000318, 0xC0004938, 0xCBC000F8, 0xC0004878, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x58240018,
+ 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000,
+ 0xC62C0078, 0xC6270038, 0xC0004940, 0xCE400038, 0xC6260038, 0xC0004942, 0xCE400038, 0xC000493C,
+ 0xCA0000F8, 0x5EEC0000, 0x8400018A, 0x5A6C0010, 0x46254000, 0x88000190, 0x5A600052, 0x46E54000,
+ 0x88000178, 0x58380006, 0xCA8000F8, 0xC0004940, 0xCA0000F8, 0xC2400000, 0xC6A70038, 0x7E412000,
+ 0x76612000, 0xC2000000, 0xC6A10038, 0x46250000, 0x84000138, 0xC0004942, 0xCA0000F8, 0xC2400000,
+ 0xC6A60038, 0x7E412000, 0x76612000, 0xC2000000, 0xC6A00038, 0x58380002, 0xCA8000F8, 0x46250000,
+ 0x840000E8, 0xC2400000, 0xC6A60078, 0x466D0000, 0x880000DA, 0xC2400000, 0xC6A40078, 0x58380008,
+ 0xCA8000F8, 0x46E50000, 0x880000BA, 0x00000000, 0xA6820018, 0x00000000, 0xC7700B00, 0xA6840098,
+ 0x00000000, 0xC7700A00, 0x80000080, 0xC7700200, 0xC000493C, 0xCAC000F8, 0x80000060, 0xC7700300,
+ 0xC000493C, 0xCAC000F8, 0x80000040, 0xC7700900, 0x80000030, 0xC7700800, 0x80000020, 0xC7700700,
+ 0x80000010, 0xC7700500, 0xC0004944, 0xCF0000F8, 0xC000493E, 0xCEC000F8, 0xC0004938, 0xCA4000F8,
+ 0xC000493C, 0xCB8000F8, 0xC000493E, 0xCB4000F8, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000,
+ 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000078, 0xC0004934, 0xCA0000F8, 0xC2400000, 0xC0004930,
+ 0xCA42E008, 0xC3C00018, 0xA6020098, 0x00000000, 0x43656000, 0x47AD0000, 0x88000050, 0x46F96000,
+ 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00008, 0x5E200000, 0x84000042, 0x5BFC0002, 0x80000030,
+ 0xC3C00004, 0x5A2C0008, 0x47A10000, 0x88000012, 0x5FB80008, 0x6FE04000, 0x42390000, 0x47212000,
+ 0x88000068, 0xC2400000, 0xC0004930, 0xCA42E008, 0xC2060002, 0xC68000F8, 0xCE006300, 0x6FE04000,
+ 0x4721C000, 0x5F700010, 0x4765A000, 0xC2000000, 0xC6340008, 0xC25A000A, 0xC000491A, 0xCA401C18,
+ 0xC2800000, 0xC0004932, 0xCA8000D8, 0xC0004862, 0xCA400060, 0x6FA04010, 0x42290000, 0xC000491E,
+ 0xCE0000F8, 0xC7E41048, 0xC000491C, 0xCE4000F8, 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF8000F8,
+ 0xC000493E, 0xCF4000F8, 0xC000493A, 0xCFC000F8, 0x80000008, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2000000, 0xDCE000F8, 0xA622FFD8, 0xC1220002, 0xD90C00F8, 0xC0004938, 0xCBC000F8, 0xC0004944,
+ 0xCB4000F8, 0xC0004862, 0xCB0000F8, 0xC0004934, 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0xA6020298, 0xC2400000, 0x58380008, 0xCA406000, 0xDFE800F8, 0xC2218E08, 0x5A21BAF6,
+ 0x46A14000, 0x84000022, 0xC2080002, 0x7361A000, 0x80000058, 0x5E640000, 0x84000022, 0xC20C0002,
+ 0x7361A000, 0x80000030, 0xC2000000, 0xC760E710, 0xC7604218, 0x5E200000, 0x840002A2, 0xC2200002,
+ 0xC0004930, 0xCE021000, 0x99008690, 0xC0004828, 0xC94000F8, 0xC1800002, 0xC0004780, 0xC93C00F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C00F8, 0x58380000, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0xA6000132, 0xC0004940, 0xCA8000F8, 0xC0004942, 0xCA4000F8, 0xC7600078, 0xC6A01838, 0xC6601038,
+ 0xC000493A, 0xCA4000F8, 0xC0004934, 0xCA8000F8, 0xC0007800, 0x40300000, 0x40240000, 0x5C000004,
+ 0x5EC07A00, 0x88000012, 0x5C000200, 0xCE0000F8, 0x58000002, 0x5EC07A00, 0x88000012, 0x5C000200,
+ 0xCE8000F8, 0xC000493E, 0xCA0000F8, 0xC2400000, 0x5838000C, 0xCE4000F8, 0x99008690, 0xC0004830,
+ 0xC94000F8, 0xC61800F8, 0xC0004930, 0xC6100078, 0xCD000078, 0x800000A8, 0xC2400002, 0x58380008,
+ 0xCE400000, 0xC0004944, 0xCF4000F8, 0x800002A8, 0xC000493C, 0xCA4000F8, 0xDFE800F8, 0x5A300018,
+ 0xC0007800, 0x40200000, 0xCA0000F8, 0x58380008, 0xC6501078, 0xCD021078, 0x5838000A, 0xCE8000F8,
+ 0x58380026, 0xCE0000F8, 0xC0004944, 0xCF4000F8, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048,
+ 0x80000068, 0x00000000, 0x99008690, 0xC0004826, 0xC94000F8, 0xC1800002, 0xC0004760, 0xC93C00F8,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C00F8, 0x8000FDA8, 0xC2000000, 0xC2400080, 0xDF600038,
+ 0xB624FFEA, 0xC000491C, 0xCA4000F8, 0xC000491E, 0xCA8000F8, 0x99007F18, 0xDA5800F8, 0xDA9800F9,
+ 0x00000000, 0xC0004934, 0xCA0000F8, 0x00000000, 0xC2800000, 0xA6020160, 0xC2400004, 0xC2000200,
+ 0xDF690048, 0x46294000, 0x46A54000, 0x8800FFDA, 0x00000000, 0xC000491A, 0xC98000F8, 0xC0004862,
+ 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC4C80, 0x99007D78, 0xD95800F8, 0xD99800F9, 0xD9D400F8,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC2000000, 0xC2400080, 0xDF600038, 0xB624FFEA,
+ 0xC000491C, 0xCA4000F8, 0xC000491E, 0xCA8000F8, 0x99007F18, 0xDA5800F8, 0xDA9800F9, 0x00000000,
+ 0x58380008, 0xCA4000F8, 0xC2000000, 0xCE000018, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE021078, 0x5838000A,
+ 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0000838, 0xC2500002, 0xCE450800, 0xC0004848, 0xCBC400F8, 0xC3800000, 0xC000082C, 0xCB840028,
+ 0x5FFC0002, 0xC0004848, 0xCFC400F8, 0x58880002, 0x47888000, 0xC1000000, 0xC50800FE, 0xC0004844,
+ 0xCC8400F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000CBF0, 0xC2000000, 0xDF600038,
+ 0x5E200080, 0x8400029A, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000480C, 0xCA0000F8, 0xC0004910, 0xCA4000F8, 0xC000492C, 0xCA8000F8,
+ 0xC0004968, 0xCAC000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x76250000, 0x76290000,
+ 0x76E16000, 0x840001DA, 0xC0004926, 0xCA4000F8, 0xC201FFFE, 0x76E16000, 0x5A640002, 0x6AE50010,
+ 0x5F200000, 0x8400001A, 0x6A250000, 0x80000010, 0xC6E000F8, 0x62014008, 0xC0004926, 0xCE8000F8,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004968,
+ 0xCA4000F8, 0xC2000002, 0x6A290000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x6EB4A000, 0x6E944000, 0x4755A000, 0x4769A000, 0x5B747000, 0x58340002,
+ 0xC2000000, 0xCA0000D8, 0x5834002E, 0xC2400000, 0xCA400078, 0x6EB0A000, 0x6EBC4000, 0x473D8000,
+ 0x47298000, 0x5B30302E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380060, 0xC6B81C18,
+ 0x99007F18, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC2000000, 0xDF600038, 0x5E200080, 0x840002D2,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA0000F8, 0xC000492A, 0xCA4000F8, 0xC000496A, 0xCB0000F8, 0xC0004956, 0xCAC000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x77218000, 0x77258000, 0x8400021A, 0xC201FFFE,
+ 0x77218000, 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x8400001A, 0x6A2D0000, 0x80000010, 0xC72000F8,
+ 0x62016008, 0xC0004956, 0xCEC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000496A, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000,
+ 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6EF4A000, 0x6ED44000, 0x4755A000,
+ 0x476DA000, 0x5B747000, 0x5834000E, 0xC2000000, 0xCA0000D8, 0x58340008, 0xC2400000, 0xCA420078,
+ 0x5834000C, 0xC2800000, 0xCA832010, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008,
+ 0xCB809018, 0x58340008, 0xC2800000, 0xCA810010, 0x6EE0A000, 0x6EE44000, 0x46250000, 0x462D0000,
+ 0x5A200008, 0x5A203008, 0x42290000, 0xC6380060, 0xC6F81C18, 0x99007F18, 0xDB9800F8, 0xDBD800F9,
+ 0x00000000, 0xC000495A, 0xC84000F8, 0x00000000, 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC0001A1C,
+ 0xCA0000F8, 0xC2400008, 0x6A452000, 0x76250000, 0x84000E9A, 0xC0000A28, 0xC3800000, 0xCB840028,
+ 0xC0000A14, 0xC3400000, 0xCB440028, 0xC0004880, 0xCB0400F8, 0x47B48000, 0x88000E48, 0x58041802,
+ 0xCAC000F8, 0xA7000060, 0x00000000, 0x00000000, 0xA6C8C5C8, 0xC2800000, 0xC6E80018, 0x80000070,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000C590, 0x00000000, 0xC2800000, 0xC7282018, 0xC000490E,
+ 0xCA4000F8, 0x6BE9E000, 0x00000000, 0x767D2000, 0x8400C548, 0x6EA0A000, 0x6E944000, 0x46150000,
+ 0x46290000, 0x5A207000, 0x5820000C, 0xCA0000F8, 0xC0004946, 0xCE8000F8, 0xA6220398, 0x00000000,
+ 0xC2200060, 0xC0004948, 0xCE000008, 0xCE021038, 0xC240000A, 0xC000494A, 0xCE4000F8, 0xC2B60002,
+ 0xC0004964, 0xCE837B00, 0x990081E8, 0xC00048A0, 0xC88400F8, 0x00000000, 0xC0004946, 0xCBC000F8,
+ 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87000, 0x99007FA8,
+ 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC000491C,
+ 0x990081A0, 0xC94000F9, 0xC98000F8, 0x00000000, 0x99007F18, 0xD95800F8, 0xD99800F9, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0,
+ 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6FF8A000,
+ 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87000, 0x58380010, 0xCA0000F8, 0xC0004874, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA4000F8, 0xC43400F8, 0x00000000, 0xC74000F8,
+ 0xCE0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA4000F8, 0xC2800002, 0x6ABD4000, 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x14100000, 0x99008690, 0xC0004836, 0xC94000F8, 0xC1800002, 0x00000000, 0x00000000,
+ 0x00000000, 0xA8E2FFE8, 0x00000000, 0xC1220002, 0xD90C00F8, 0xC2000000, 0xC0000A14, 0xCA040028,
+ 0xC0000A28, 0xC2500002, 0xCE450800, 0x58880002, 0xB6080018, 0xC00048A0, 0xC0800000, 0xCC8400F8,
+ 0x8000C168, 0xC0004946, 0xCBC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000490E, 0xCA4000F8, 0xC2800002, 0x6ABD4000, 0x72692000, 0xCE4000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x58380008, 0xCA0000F8, 0x5838000C, 0xCA4000F8, 0xC3400000, 0xC6340000, 0xC000494E,
+ 0xCF4000F8, 0xC2800000, 0xC62A0078, 0xC3000000, 0xC6308018, 0x6F304000, 0x43298000, 0xC000493C,
+ 0xCF0000F8, 0xC2C00000, 0xC66C0078, 0xC0004950, 0xCEC000F8, 0xC2800000, 0xC66AE020, 0xC0004954,
+ 0xCE8000F8, 0x5F740000, 0x840001B8, 0x5E300028, 0x46E12000, 0x84000182, 0x46E12000, 0x8800014A,
+ 0x5E300018, 0x46E12000, 0x8800002A, 0x46E12000, 0x84000042, 0x00000000, 0x800000D8, 0x00000000,
+ 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC3400002, 0xC000494E, 0xCF4000F8, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000490E, 0xCA4000F8,
+ 0xC2800002, 0x6ABD4000, 0x7E814000, 0x76692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x14100000, 0xC2200060, 0xC0004948, 0xCE021038, 0xC2000000, 0xC000494C, 0xCE0000F8, 0x80000080,
+ 0x00000000, 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99008528, 0xDBD800F8, 0xDB9800F9,
+ 0xC78000F8, 0xC2200058, 0xC0004948, 0xCE021038, 0xC2000002, 0xC000494C, 0xCE0000F8, 0xC2000006,
+ 0xC0001006, 0xCE0000F8, 0x5838000A, 0xCA4000F8, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE0000F8,
+ 0xC000100A, 0xCE4000F8, 0xC0004954, 0xCA8000F8, 0xC200000C, 0xC000494A, 0xCE0000F8, 0xC0004948,
+ 0xCE800008, 0xC2B60000, 0xC0004964, 0xCE8000F8, 0x990081E8, 0xC00048A0, 0xC88400F8, 0x00000000,
+ 0xC0004946, 0xCBC000F8, 0xC000494C, 0xCA0000F8, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000,
+ 0x5BB87000, 0x5E200000, 0x84000112, 0x00000000, 0x99007FA8, 0xDBD800F8, 0xDB9800F9, 0x00000000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420048, 0xC000491C, 0x990081A0, 0xC94000F9, 0xC98000F8,
+ 0x00000000, 0x99007F18, 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0, 0xDBD800F8, 0xDB9800F9, 0xC7D800F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0xC000493C, 0xCA8000F8, 0xC000494E, 0xCAC000F8,
+ 0xC3000018, 0xC3400006, 0x5E200000, 0x8400002A, 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000,
+ 0xC6AC1078, 0xC72C0418, 0xC76C0810, 0x58380010, 0xCA8000F8, 0x58380008, 0xCEC000F8, 0xC6280100,
+ 0xC0004874, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCB0000F8, 0xC43400F8,
+ 0x00000000, 0xC74000F8, 0xCE8000F8, 0xC0004952, 0xCE8000F8, 0x00000000, 0x00000000, 0x00000000,
+ 0xA8E2FFE8, 0x00000000, 0xC000494C, 0xCA0000F8, 0xC0004950, 0xCAC000F8, 0x5E200000, 0x8400006A,
+ 0xDFE800F8, 0x7E814000, 0x5834001A, 0xCE8000F8, 0x99008690, 0xC0004834, 0xC94000F8, 0xC1800002,
+ 0x99008690, 0xC0004838, 0xC94000F8, 0xC6D800F8, 0xC1220002, 0xD90C00F8, 0x5E200000, 0x84000040,
+ 0x5838002C, 0xCB0000F8, 0xDFE800F8, 0x00000000, 0x58380014, 0xCF0000F8, 0x80000018, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0x5838000A, 0xCE8000F8, 0xC3000000, 0xC0000A14, 0xCB040028, 0xC2D00002, 0xC0000A28,
+ 0xCEC50800, 0xC000494E, 0xCA8000F8, 0x58880002, 0xB4B00018, 0xC00048A0, 0xC0800000, 0xCC8400F8,
+ 0x5EA80000, 0x8400016A, 0x5E200000, 0x84000158, 0xC000493C, 0xCA8000F8, 0x00000000, 0x00000000,
+ 0x5AA80060, 0xCE8000F8, 0x99008328, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99008528, 0xDBD800F8,
+ 0xDB9800F9, 0xC78000F8, 0xC0004952, 0xCAC000F8, 0x58380000, 0xCA8000F8, 0xC30C0002, 0xC7F00018,
+ 0xA68000B0, 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC0001800, 0xCA0000F8, 0x00000000, 0x00000000, 0xA60CFFEA, 0xC6F00500,
+ 0xC6B0C400, 0xCF0000F8, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x14100000, 0x8000B7B8, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000B750, 0xDCBC00F9, 0x5FFC0000, 0x8400095A, 0xC3800002,
+ 0xDB8800F9, 0xC3800000, 0xDB8800F9, 0xC0004728, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xC0004730, 0xC98000F8, 0xC000472E, 0xC94000F8, 0xC00047DC, 0xC90000F8, 0xC00047DE,
+ 0xC9C000F8, 0xC000472E, 0xCD8000F8, 0x6D110000, 0xC5D30038, 0xC00047DC, 0xCD0000F8, 0x4594A000,
+ 0x6DDD0000, 0xC55C0038, 0xC00047DE, 0xCDC000F8, 0xC0001AC4, 0xC94000F8, 0xC0001AC8, 0xC98000F8,
+ 0xC000472C, 0xC9C000F8, 0x45948000, 0xC1000002, 0x41D0E004, 0xCDC000F8, 0xC5501078, 0xC5900078,
+ 0xC000472A, 0xCD0000F8, 0xC0001AF0, 0xCBC000F8, 0x58000002, 0xCB8000F8, 0xC3400000, 0xC7F50038,
+ 0x6F702000, 0x5B304300, 0xC000474C, 0xCAC000F8, 0xC0004720, 0xC94000F8, 0x00000000, 0x00000000,
+ 0x5D940002, 0x6D9B8000, 0x6D9B8010, 0x581847E0, 0xC98000F8, 0x581447E0, 0xC9C000F8, 0x5D2C0000,
+ 0x8400007A, 0xC7901078, 0xC7D00078, 0xCD0000F8, 0xC1000000, 0xC5910038, 0x45348000, 0x84000090,
+ 0xC0004722, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x80000058, 0xC1000000,
+ 0xC5D10038, 0x45348000, 0x8400003A, 0xC0004724, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xA7840080, 0x59540002, 0x6D578000, 0x6D578010, 0xC0004720, 0xCD4000F8, 0xC1000000,
+ 0xC5910038, 0x45348000, 0x84000038, 0xC0004726, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD0000F8, 0xA78000B8, 0xC2800002, 0xC000474E, 0xCE8000F8, 0xC2C00000, 0xC000474C, 0xCEC000F8,
+ 0xC0004758, 0xCFC000F8, 0x58000002, 0xCF8000F8, 0xC000475C, 0xC90000F8, 0x00000000, 0x00000000,
+ 0xA53E003A, 0x00000000, 0xC13E0002, 0xCFC000F8, 0xCD03DE08, 0x58000002, 0xCF8000F8, 0x800001A0,
+ 0xC000475C, 0xC13C0002, 0xCD03DE08, 0x5D2C0000, 0x8400017A, 0xC2C00000, 0xC000474C, 0xCEC000F8,
+ 0x98C08AF0, 0xC75400F8, 0xC0004740, 0xC9C000F8, 0x5D240000, 0x84000042, 0xC1000002, 0xC0004750,
+ 0xCD0000F8, 0xC0004752, 0xCD0000F8, 0x80000100, 0x00000000, 0x98C08BE0, 0xC75400F8, 0xC0004742,
+ 0xC98000F8, 0x5D240000, 0x8400002A, 0xC1000002, 0xC0004752, 0xCD0000F8, 0x80000060, 0xC0004742,
+ 0xC94000F8, 0xC0004754, 0xC1000002, 0xCD0000F8, 0x98C08CF0, 0xC55400F8, 0xC75800F8, 0x00000000,
+ 0xC0004742, 0xCF4000F8, 0x98C08AB8, 0xC1400000, 0xC7540020, 0x6F40A010, 0xC1000000, 0xC7D00038,
+ 0x58300000, 0x6D110000, 0xCD010838, 0xA7840398, 0xC000474C, 0xCAC000F8, 0xC000474E, 0xCA8000F8,
+ 0xC0004750, 0xCBC000F8, 0xC0004752, 0xCB8000F8, 0xC0004710, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0x5D280002, 0x840000B8, 0xC000473C, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0xC0004712, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0xC0004754, 0xC90000F8, 0x00000000, 0x00000000, 0x5D100000, 0x8400021A, 0x58300000, 0xC13C0002,
+ 0xCD03DE00, 0x800001F8, 0xC0004714, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x5D380000, 0x8400003A, 0xC0004736, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x5D3C0000, 0x84000042, 0xC0004718, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8,
+ 0x80000140, 0xC1000000, 0x58300000, 0xC903E000, 0x00000000, 0x00000000, 0x5D100000, 0x84000042,
+ 0xC000471A, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x800000D0, 0x58300000,
+ 0xC13E0002, 0xCD03FF00, 0xC1000000, 0x58300000, 0xC903C000, 0x00000000, 0x00000000, 0x5D100000,
+ 0x84000082, 0xC0004716, 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0xC000473A,
+ 0xC90000F8, 0x00000000, 0x00000000, 0x59100002, 0xCD0000F8, 0x58300000, 0xC13C0000, 0xCD03DE00,
+ 0xC1000000, 0xC0004746, 0xCD0000F8, 0xC0004750, 0xCD0000F8, 0xC0004752, 0xCD0000F8, 0xC000474E,
+ 0xCD0000F8, 0xC2C00002, 0xC000474C, 0xCEC000F8, 0xC0004754, 0xCD0000F8, 0xC3CE0002, 0xC0000800,
+ 0xCFC0E700, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC43800F8, 0x00000000,
+ 0xC000480E, 0xCA0000F8, 0xC0004858, 0xCB4400F8, 0x00000000, 0x00000000, 0x47610000, 0x880000B0,
+ 0x00000000, 0xA7C00048, 0xC0004854, 0xC1000002, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x800000D8, 0x00000000, 0xA7D20138, 0x00000000, 0xC7E14040, 0xC2400000, 0xC6246028, 0xC200006A,
+ 0x46250000, 0xC6240030, 0xC0000810, 0xCE440030, 0x8000FF70, 0xC2000000, 0xC0000808, 0xCA040010,
+ 0xC11C0000, 0xC000082C, 0xCD05CE00, 0x5A200002, 0x5E600010, 0x84000010, 0xC2000000, 0xC0000808,
+ 0xCE040010, 0xC3400000, 0x80000028, 0xC1200002, 0xC0000818, 0xCD061000, 0x5B740002, 0xC0004858,
+ 0xCF4400F8, 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD05CE00,
+ 0x80000878, 0x5B740002, 0xC0004858, 0xCF4400F8, 0xC78000F8, 0xC13C0002, 0xCD03DE00, 0xC0004848,
+ 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848, 0xCD4400F8, 0x58880002,
+ 0xB49807F8, 0x00000000, 0xC0800000, 0x800007E0, 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000,
+ 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000, 0xA7C00130, 0xC000484C, 0xCA0400F8, 0xC2400000,
+ 0xC0001AEC, 0xCA440018, 0x5A200002, 0xC000484C, 0xCE0400F8, 0xB624008A, 0xC68000F8, 0xC13C0002,
+ 0xCD03DE00, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848,
+ 0xCD4400F8, 0x58880002, 0xB49806E8, 0x00000000, 0xC0800000, 0x800006D0, 0xC0004854, 0xC1000004,
+ 0xCD0400F8, 0xC0000820, 0xC2000002, 0xCE0400F8, 0xC2000000, 0xC000484C, 0xCE0400F8, 0xC0004858,
+ 0xCE0400F8, 0x8000FF28, 0xC0004854, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC1200000, 0xC0000818, 0xCD061000, 0xC11C0002,
+ 0xC000082C, 0xCD05CE00, 0xC2000000, 0xC000484C, 0xCE0400F8, 0x800005D0, 0xC0001AC0, 0xCB8400F8,
+ 0xC000487C, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000,
+ 0xA78004E2, 0x00000000, 0x00000000, 0xA7C004A2, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE046308,
+ 0xA7E8045A, 0x00000000, 0xC0004850, 0xCA0400F8, 0xC2400000, 0xC0004812, 0xCA420078, 0x5A200002,
+ 0xC0004850, 0xCE0400F8, 0x5E640000, 0x8400001A, 0x46250000, 0x880002F8, 0xC68000F8, 0xC13C0002,
+ 0xCD03DE00, 0xC0001ACC, 0xC2000002, 0xCE040000, 0x5C440000, 0x84000250, 0xC0004810, 0xC94000F8,
+ 0xC68000F8, 0xCBC000F8, 0x00000000, 0xC1000000, 0xA5400208, 0xC53C1000, 0x00000000, 0xA7FC01F2,
+ 0xC0001AF0, 0xC1000000, 0x58000002, 0xC9000000, 0xC000474E, 0xC98000F8, 0x5D100000, 0x84000022,
+ 0xC1000002, 0xC53C1E00, 0x80000198, 0x5D180000, 0x84000022, 0xC1000002, 0xC53C1E00, 0x80000170,
+ 0xC0004878, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xC98000F8, 0xC43800F8,
+ 0x00000000, 0xC000481E, 0xC9C000F8, 0xC000481C, 0xCA0000F8, 0x00000000, 0x759CC000, 0x45A08000,
+ 0x840000E8, 0xC0001AF0, 0xC3400000, 0x58000000, 0xCB410038, 0xC0004746, 0xC94000F8, 0x6F702000,
+ 0x5B304300, 0xC2C00000, 0x58300000, 0xCAC00038, 0x00000000, 0x00000000, 0x456C8000, 0x88000020,
+ 0xC1000002, 0xC53C1E00, 0x80000040, 0x5AEC0002, 0x58300000, 0xCEC00038, 0xC1000002, 0xC53C1000,
+ 0xC77C0838, 0xC57C0038, 0x59540002, 0xC0004746, 0xCD4000F8, 0xC68000F8, 0xCFC000F8, 0xC0004848,
+ 0xC94400F8, 0xC1800000, 0xC000082C, 0xC9840028, 0x59540002, 0xC0004848, 0xCD4400F8, 0x58880002,
+ 0xB49801F8, 0x00000000, 0xC0800000, 0x800001E0, 0xC000471E, 0xC90000F8, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD0000F8, 0xC0004854, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000082C, 0xCD05CE00,
+ 0x99007930, 0xC0004848, 0xC94400F8, 0xC1800000, 0xC2000000, 0xC0000820, 0xCE0400F8, 0xC1200000,
+ 0xC0000818, 0xCD061000, 0xC11C0002, 0xC000082C, 0xCD05CE00, 0xC0004850, 0xCE0400F8, 0xC2000002,
+ 0xC0001ACC, 0xCE040008, 0x800000E8, 0xC2000002, 0xC0004850, 0xCE0400F8, 0x8000FC00, 0xC2000000,
+ 0xC0004850, 0xCE0400F8, 0xA7E60032, 0x00000000, 0xC2000002, 0xC0001B00, 0xCE040000, 0x8000FBE8,
+ 0x00000000, 0xA7860052, 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC2020002, 0xC7E2A540,
+ 0xC0001B00, 0xCE0400F8, 0x8000FB90, 0xC2040002, 0xC0001B00, 0xCE044200, 0x8000FB70, 0xC2C80002,
+ 0x6AC56000, 0xDACC00F8, 0xC0004854, 0xCB4400F8, 0xC0004848, 0xCB8400F8, 0xC0000838, 0xC3C00000,
+ 0xCBC40028, 0x5EF40004, 0x84000022, 0xC3000000, 0xC0001ACC, 0xCF042100, 0x47F98000, 0x8400004A,
+ 0x47F98000, 0x88000050, 0xC1006E8C, 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0004840, 0xCC8400F8, 0x8000EB10, 0xC0001AC0, 0xCAC400F8, 0xC0004854, 0xCB4400F8, 0xA6C0F93A,
+ 0x00000000, 0x5EF40000, 0x8400F472, 0x5EF40002, 0x8400F702, 0x5EF40004, 0x8400F902, 0xC1006CE8,
+ 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0800000, 0xDF4B0038,
+ 0xC0004900, 0xCB8000F8, 0xC2000000, 0xC000490A, 0xA78000D0, 0xCBC000F8, 0xC1000000, 0xD90000F9,
+ 0xC1000002, 0xD90C00F8, 0x6FF46000, 0x477DA000, 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400078,
+ 0xC0004900, 0xCE000000, 0x5A640002, 0x58340004, 0xC6500078, 0xCD000078, 0xC0004914, 0xCA4000F8,
+ 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0xC0000408, 0xCE0000F8, 0xA78200D8, 0xC0004908,
+ 0xCBC000F8, 0xC1000000, 0xD90000F9, 0xC1000002, 0xD90C00F8, 0x6FF4A000, 0x6FD44000, 0x4755A000,
+ 0x477DA000, 0x5B747000, 0xC2800000, 0x58340006, 0xCA800078, 0xC2000000, 0xC0004900, 0xCE002100,
+ 0x5EA80002, 0x58340006, 0xC6900078, 0xCD000078, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408,
+ 0xCE0000F8, 0xC0000032, 0xDCA800F9, 0xC1000002, 0x45294000, 0x00000000, 0x8C100006, 0x00000000,
+ 0x00000000, 0x00000000, 0xA4800230, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00018, 0xC3400000,
+ 0xC2400000, 0x6FF86000, 0x47BDC000, 0x5BB84C80, 0x58380008, 0xCB400078, 0x58380006, 0xCA400078,
+ 0x5F740002, 0x58380008, 0xC7500078, 0xCD000078, 0xC2000000, 0x58380004, 0xCA020078, 0xC3000000,
+ 0x5838000C, 0xCB000020, 0x5A640002, 0x46610000, 0x84000010, 0xC2400000, 0x58380006, 0xC6500078,
+ 0xCD000078, 0xC2000000, 0x5838000A, 0xCA020078, 0x5B300002, 0x5838000C, 0xC7100020, 0xCD000020,
+ 0xC2420020, 0x5A200004, 0x46252000, 0x84000010, 0xC2000000, 0x5838000A, 0xC6101078, 0xCD021078,
+ 0xC0004966, 0xCA4000F8, 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0x5F740000, 0x84000040,
+ 0xC0004912, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x5F300020,
+ 0x84000040, 0xC0004924, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8,
+ 0xA4820070, 0xC2400000, 0xC000140E, 0xCA408018, 0xC2000002, 0xC0004900, 0xCE000000, 0xC000490A,
+ 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA48402A8, 0x00000000,
+ 0xC3C00000, 0xC000140E, 0xCBC10018, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4795C000,
+ 0x47BDC000, 0x5BB87000, 0x5838002E, 0xCA800078, 0x58380006, 0xCA020078, 0xC3400000, 0x5838002E,
+ 0xCB420078, 0x5AA80002, 0x46A10000, 0x84000010, 0xC2800000, 0x5838002E, 0xC6900078, 0xCD000078,
+ 0x5F740002, 0x5838002E, 0xC7501078, 0xCD021078, 0xC0004968, 0xCA4000F8, 0xC2000002, 0x6A3D0000,
+ 0x72612000, 0xCE4000F8, 0xC000492A, 0xCA8000F8, 0x5E740000, 0x84000040, 0xC0004910, 0xCA0000F8,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x6ABD4010, 0xA68000F2, 0x00000000,
+ 0xC0004910, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x58380032,
+ 0xCA0000F8, 0x58000002, 0xCA4000F8, 0x5838000C, 0x00000000, 0xCE0000F9, 0xCE4000F8, 0xC000492A,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0xC000492C, 0xCA0000F8, 0xC2C00002,
+ 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0x80000040, 0xC000492C, 0xCA0000F8, 0xC2C00002, 0x6AFD6000,
+ 0x7EC16000, 0x762D0000, 0xCE0000F8, 0xA4880120, 0xC2C00000, 0xC000140E, 0xCAC20018, 0xC000490E,
+ 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8, 0xC000496A, 0xCA4000F8,
+ 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0x6EF0A000, 0x6ED44000, 0x47158000, 0x472D8000,
+ 0x5B307000, 0x58300000, 0xCA0000F8, 0x00000000, 0xC2400002, 0x76612000, 0x8400004A, 0xC24C0002,
+ 0xC6E40018, 0xC624C400, 0x58300010, 0xCA400500, 0x00000000, 0xC0001800, 0xCE4000F8, 0xA4860070,
+ 0xC2400000, 0xC000140E, 0xCA418018, 0xC2020002, 0xC0004900, 0xCE002100, 0xC0004908, 0xCE4000F8,
+ 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA48C0048, 0xC2800002, 0xC000484A,
+ 0xCE8000F8, 0xC2800000, 0xC000474A, 0xCE8000F8, 0xC0004846, 0xCE8000F8, 0xC0001408, 0xCC8000F8,
+ 0xC10E0002, 0xD90C00F8, 0x8000EA78, 0xDFBC00F9, 0xC000496E, 0x99008638, 0xC94000F8, 0xC7D800F8,
+ 0x00000000, 0xC57000F8, 0x5EF00020, 0x88000148, 0x6F346000, 0x4771A000, 0x5B744C80, 0x58340008,
+ 0xC2400000, 0xCA400078, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400078, 0x58340004, 0xCA000078,
+ 0x00000000, 0x00000000, 0x5E200002, 0xCE000078, 0xC0004912, 0xCA8000F8, 0xC2400002, 0x6A712000,
+ 0x72A54000, 0xCE8000F8, 0x5E200000, 0x84000052, 0xC000480A, 0xCA0000F8, 0xC0000408, 0xCA8000F8,
+ 0x76250000, 0x00000000, 0x72A14000, 0xCE8000F8, 0x80000038, 0xC0004914, 0xCA0000F8, 0x7E412000,
+ 0x00000000, 0x76250000, 0xCE0000F8, 0x800000D0, 0x6EF4A000, 0x6ED44000, 0x4755A000, 0x476DA000,
+ 0x5B747000, 0x5834002E, 0xC2400000, 0xCA420078, 0x00000000, 0xC2000000, 0x5A640002, 0xC6501078,
+ 0xCD021078, 0x58340006, 0xCA000078, 0x00000000, 0x00000000, 0x5A200002, 0xCE000078, 0xC0004910,
+ 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0xC2000002, 0x6A310000, 0xC000042A,
+ 0xCE0000F8, 0xC1040002, 0xD90C00F8, 0x00000000, 0x8000E7E8, 0x00000000, 0xC4980928, 0x9D000000,
+ 0xC5580028, 0xC0000838, 0xCD8400F8, 0xC1440200, 0xC1C03800, 0xC55C1070, 0xC000100E, 0x9D000000,
+ 0xCD8000F8, 0xC000100C, 0xCDC000F8, 0xC0004862, 0xC9C000F8, 0x00000000, 0x00000000, 0xD9D800F9,
+ 0xC0007800, 0x401C0000, 0x5DC07A00, 0x88000012, 0x5C000200, 0xCD8000F8, 0xC1F0000A, 0x715CA000,
+ 0xDD9800F8, 0xDD9C00F9, 0x41D8E000, 0xC5D40260, 0xC0001010, 0xCD4000F8, 0x6C9C8000, 0x45C8E000,
+ 0x45C8E000, 0x59DC0004, 0xC1601260, 0xC5D40260, 0x9D000000, 0xC0001012, 0xCD4000F8, 0x00000000,
+ 0x00000000, 0xD95800F8, 0x6D586000, 0x4594C000, 0x59984C80, 0xD99800F9, 0x5818000A, 0xC1800000,
+ 0xC9800078, 0xC0006E00, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC94000F8, 0x58000002, 0x00000000,
+ 0xC9C000F8, 0xC0004930, 0xCD4000F8, 0xC0004932, 0xCDC000F8, 0x59980004, 0xC1C20020, 0xB59C0018,
+ 0x00000000, 0xC1800000, 0xDD9C00F9, 0x581C000A, 0xCD800078, 0x581C000C, 0xC1800000, 0xC9800020,
+ 0xC1C00002, 0xDD9400F8, 0x69D4E000, 0x5D980002, 0xCD800020, 0xC0004924, 0xC98000F8, 0x00000000,
+ 0x9D000000, 0x00000000, 0x719CC000, 0xCD8000F8, 0xC000492A, 0xC94000F8, 0xC1C00002, 0x69D8E000,
+ 0x7DC0C000, 0x7558A000, 0xCD4000F8, 0xC000492C, 0xC94000F8, 0xDD8000F9, 0x58000032, 0x755CA000,
+ 0x84000090, 0xC94000F9, 0xC98000F8, 0xDD8000F9, 0x5800000C, 0x00000000, 0xCD4000F9, 0xCD8000F8,
+ 0xC000492C, 0xC94000F8, 0xC000492A, 0xC98000F8, 0x715CA000, 0xC000492C, 0xCD4000F8, 0x719CC000,
+ 0xC000492A, 0xCD8000F8, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004862, 0xC98000F8,
+ 0x00000000, 0xC1C00200, 0x4194C000, 0x459CE000, 0x88000012, 0xC5D800F8, 0xC0004862, 0xCD8000F8,
+ 0xC0001406, 0xC98000F8, 0xC1C00002, 0x9D000000, 0xC5D80A00, 0xC5581048, 0xCD8000F8, 0xC0004930,
+ 0xC98000F8, 0xC0004932, 0xC9C000F8, 0xC140000E, 0xC5581C18, 0xDD9400F8, 0xC0007800, 0x40140000,
+ 0x5D407A00, 0x88000012, 0x5C000200, 0xCD8000F8, 0x58000002, 0x5D407A00, 0x88000012, 0x5C000200,
+ 0xCDC000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000, 0x58140000, 0xC98000D8,
+ 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC000F8, 0xDD9800F8, 0xC1C00022, 0xC5D80D70, 0xDD9400F9,
+ 0xC5581C18, 0xC000491C, 0xCD8000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000,
+ 0x58140004, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000, 0x9D000000,
+ 0x58140006, 0xC5D81078, 0xCD821078, 0xC0004860, 0xC94000F8, 0xC1820080, 0xC1D00002, 0x58147700,
+ 0xD58000F8, 0x58000002, 0xD58000F9, 0x59540004, 0xB5580018, 0xC0004860, 0xC1400000, 0xCD4000F8,
+ 0xDD9800F9, 0x9D000000, 0xDD9400F8, 0xC0001404, 0xCDC10800, 0xC1C00000, 0xC1800200, 0x5D980004,
+ 0xDF5D0048, 0x459CA000, 0x8800FFF2, 0xDD8000F9, 0x5800000C, 0x00000000, 0xC94000F9, 0xC98000F8,
+ 0xC1C00002, 0xC5D43F00, 0xC5D81E00, 0xC0004862, 0xC9C000F8, 0x00000000, 0x00000000, 0x581C7800,
+ 0x5DC07A00, 0x88000012, 0x5C000200, 0xCD4000F8, 0x58000002, 0x5DC07A00, 0x88000012, 0x5C000200,
+ 0xCD8000F8, 0xC0004862, 0xC9C000F8, 0x00000000, 0xC15004C0, 0xC5D40060, 0xDD9C00F8, 0xC5D41C18,
+ 0xC1C00000, 0xDD8000F9, 0x58000030, 0xC9C00078, 0xDD8000F9, 0x58000002, 0xC98000F8, 0x6DDC2000,
+ 0xC000491C, 0x41D8E000, 0xCD4000F9, 0xCDC000F8, 0xDD9400F9, 0xC1C00000, 0x58140030, 0xC9C00078,
+ 0xC1800000, 0x58140006, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000,
+ 0x9D000000, 0x58140030, 0xC5D80078, 0xCD800078, 0xC1C00000, 0xDF5C0038, 0x5DDC0080, 0x8400FFEA,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440060,
+ 0xC1A0FFFE, 0x59983008, 0xC000100C, 0xCD4000F8, 0xC000100E, 0xCD8000F8, 0xC0004964, 0xC98000F8,
+ 0x00000000, 0xC170000A, 0x7158A000, 0x6C988000, 0x4588C000, 0x4588C000, 0x59980004, 0xC5940270,
+ 0xC0001010, 0xCD4000F8, 0xC0004946, 0xC94000F8, 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000,
+ 0x459CC000, 0x4594C000, 0xC000494A, 0xC94000F8, 0xC0004948, 0xC9C000F8, 0x4194C000, 0xC1400012,
+ 0xC55C1818, 0x9D000000, 0xC59C0268, 0xC0001012, 0xCDC000F8, 0xC1400000, 0x58000012, 0xC9410038,
+ 0xC0004950, 0xC9C000F8, 0xC55800F8, 0xC5940838, 0xC5581078, 0xD99400F8, 0xC000493C, 0xC94000F8,
+ 0xC0004954, 0xC98000F8, 0x59DC00A8, 0x45D4E000, 0x41D8E000, 0x5D5C0030, 0x88000010, 0xC1C00030,
+ 0xC1800000, 0xC5D84028, 0xC1400000, 0xC5D40008, 0x5DD40002, 0x84000072, 0x5DD40004, 0x8400009A,
+ 0x5DD40006, 0x840000C2, 0x5DD80026, 0x840000EA, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000,
+ 0xCD4000F8, 0x59980002, 0x8000FFC0, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD4000B8,
+ 0x59980002, 0x8000FF88, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400078, 0x59980002,
+ 0x8000FF50, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400038, 0x59980002, 0x8000FF18,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC94000F8, 0xC0004954,
+ 0xC9C000F8, 0xC0004950, 0xC9400078, 0xDD8000F9, 0x58000028, 0x5D9C0000, 0x84000052, 0x5D9C0002,
+ 0x84000052, 0x5D9C0004, 0x8400006A, 0xC55B0038, 0xC55C08B8, 0xCD800039, 0xCDC108B8, 0x80000060,
+ 0xCD4000F8, 0x80000050, 0xC55900B8, 0xC55C1838, 0xCD8000B9, 0xCDC31838, 0x80000028, 0xC55A0078,
+ 0xC55C1078, 0xCD800079, 0xCDC21078, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x59540002,
+ 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x88000012, 0xC59400F8, 0x9D000000, 0xCD4000F8,
+ 0x00000000, 0x00000000, 0x9D000000, 0x4158A000, 0xCD4000F8, 0x00000000, 0xCD8000F9, 0x45408000,
+ 0x8800FFF0, 0x00000000, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004810, 0xCA010038,
+ 0xC241FFFE, 0xC1400000, 0x46148000, 0x00000000, 0x9CC00006, 0xC0004200, 0x40180000, 0xC9C000F8,
+ 0x00000000, 0x00000000, 0x61C08010, 0x8400005A, 0xC2400002, 0x6A512000, 0x71E4E000, 0xCDC000F8,
+ 0xC0004748, 0xCD8000F8, 0x9CC00000, 0x6D98A000, 0x5998003E, 0x45912000, 0x59540002, 0x59980002,
+ 0x46188000, 0xC1000000, 0xC51800FE, 0x8000FF38, 0x00000000, 0x40180000, 0xC9C000F8, 0xC2000000,
+ 0xC5600020, 0xC1210000, 0x69208010, 0x7D008000, 0x75D0E000, 0xCDC000F8, 0x6D542000, 0x58144300,
+ 0xC1000000, 0xCD0000F9, 0x9CC00000, 0xC121FFFE, 0x5911FFFE, 0xCD0000F9, 0x79588000, 0x6D10A010,
+ 0x5D100000, 0x840000C0, 0x45948000, 0x880000B0, 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700,
+ 0x40140000, 0xCA0000F8, 0x00000000, 0x00000000, 0x6A110000, 0x6A110010, 0x62008018, 0x84000032,
+ 0x00000000, 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45512000, 0x59540002, 0x6D57A000, 0x6D57A010,
+ 0x6D54A000, 0x6D936000, 0x6D136010, 0xC1E10000, 0x69D0E010, 0x5DDC0002, 0x7DC0E000, 0x6D98A010,
+ 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700, 0x40140000, 0xCA0000F8, 0x00000000, 0x00000000,
+ 0x6A110000, 0x6A110010, 0x45588000, 0x00000000, 0x761D0002, 0x62008018, 0x84000032, 0x00000000,
+ 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45512000, 0x45588000, 0x00000000, 0x9CC00002, 0x59540002,
+ 0x6D57A000, 0x6D57A010, 0xC0004700, 0x40140000, 0xCA0000F8, 0x8000FF68, 0x00000000, 0x00000000,
+ 0x00000000, 0x58004700, 0xC98000F8, 0x9CC00000, 0x00000000, 0x6994C000, 0x6DA7E010, 0x58004700,
+ 0xC98000F8, 0xC1210000, 0x9CC00000, 0x69148010, 0x7190C000, 0xCD8000F8, 0xC1000000, 0xC0004810,
+ 0xC9020038, 0x00000000, 0x00000000, 0x45D0C000, 0x88000062, 0xC2400002, 0x45588000, 0xC1000000,
+ 0xC52400FC, 0x45D48000, 0xC1000000, 0xC52400FE, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59980200, 0xC2400000, 0x455C8000, 0xC1000002, 0xC52400FC, 0x45948000, 0xC1000002, 0xC52400FE,
+ 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004740, 0xC9C000F8, 0x59180002, 0x6D130000,
+ 0x6D130010, 0x451C8000, 0xC2400000, 0x9CC00002, 0x00000000, 0x00000000, 0x459C8000, 0x88000062,
+ 0xC2400002, 0x455C8000, 0xC1000000, 0xC52400FC, 0x45948000, 0xC1000000, 0xC52400FC, 0x9CC00000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC2400000, 0x45588000, 0xC1000002, 0xC52400FE, 0x45D48000,
+ 0xC1000002, 0xC52400FE, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6D570000,
+ 0x6D570010, 0x45588000, 0x6D402000, 0x9CC00002, 0x58004300, 0x58000000, 0xC13C0002, 0xCD03DE00,
+ 0x8000FFB0, 0x00000000, 0x00000000, 0x00000000, 0xC1020002, 0xD90C00F8, 0xC98000F8, 0x59540002,
+ 0xC0004730, 0xCD4000F8, 0x5D980002, 0x00000000, 0x80000036, 0x00000000, 0x9CC00000, 0xC0004732,
+ 0xCD8000F8, 0x00000000, 0xC0004734, 0xC9C000F8, 0xC1800000, 0xC0004816, 0xC9820078, 0xC0004738,
+ 0xCDC000F8, 0xC1C00000, 0xC0004734, 0x9CC00000, 0xCDC000F8, 0xC0004732, 0xCD8000F8,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_AR9_H
diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_danube.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_danube.h new file mode 100644 index 0000000000..fff0d31e5e --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_danube.h @@ -0,0 +1,440 @@ +#ifndef IFXMIPS_ATM_FW_DANUBE_H +#define IFXMIPS_ATM_FW_DANUBE_H + + +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_danube.h +** PROJECT : Danube +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PP32 Firmware) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +*******************************************************************************/ + + +#define VER_IN_FIRMWARE 1 + +#define ATM_FW_VER_MAJOR 0 +#define ATM_FW_VER_MINOR 17 + + +static unsigned int firmware_binary_code[] = { + 0x800004A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFC8, 0x00000000, 0x00000000, 0x00000000, + 0xC1000002, 0xD90C0000, 0xC2000002, 0xDA080001, 0x80004968, 0xC2000000, 0xDA080001, 0x80003FD0, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003F88, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80005160, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003E88, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC0400000, 0xC0004840, 0xC8840000, 0x80004628, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC0400002, 0xC0004840, 0xC8840000, 0x800045A8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC3C00004, 0xDBC80001, 0xC10C0002, 0xD90C0000, 0x8000FEC8, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC10E0002, 0xD90C0000, 0xC0004808, 0xC8400000, 0x800045D8, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481, + 0x00000000, 0x00000000, 0x00000000, 0xC3C00000, 0xDBC80001, 0xC1400008, 0xC1900000, 0x71948000, + 0x15000100, 0xC140000A, 0xC1900002, 0x71948000, 0x15000100, 0xC140000C, 0xC1900004, 0x71948000, + 0x15000100, 0xC1400004, 0xC1900006, 0x71948000, 0x15000100, 0xC1400006, 0xC1900008, 0x71948000, + 0x15000100, 0xC140000E, 0xC190000A, 0x71948000, 0x15000100, 0xC1400000, 0xC190000C, 0x71948000, + 0x15000100, 0xC1400002, 0xC190000E, 0x71948000, 0x15000100, 0xC0400000, 0xC11C0000, 0xC000082C, + 0xCD040E08, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD040E08, + 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0000824, 0x00000000, 0xCBC00001, 0xCB800001, 0xCB400001, + 0xCB000000, 0xC0004878, 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800001, 0x5B744000, 0xCF400001, + 0x5B304000, 0xCF000000, 0xC0000A10, 0x00000000, 0xCBC00001, 0xCB800000, 0xC0004874, 0x5BFC4000, + 0xCFC00001, 0x5BB84000, 0xCF800000, 0xC30001FE, 0xC000140A, 0xCF000000, 0xC3000000, 0x7F018000, + 0xC000042E, 0xCF000000, 0xC000040E, 0xCF000000, 0xC3C1FFFE, 0xC000490E, 0xCFC00080, 0xC000492C, + 0xCFC00080, 0xC0004924, 0xCFC00040, 0xC0004912, 0xCFC00040, 0xC0004966, 0xCFC00040, 0xC0004968, + 0xCFC00080, 0xC000496A, 0xCFC00080, 0xC3C1FFFE, 0xC00049A0, 0xCFC00000, 0xC3C00000, 0xC2800020, + 0xC3000000, 0x7F018000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF000000, + 0x5BFC0002, 0xB7E8FFA8, 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47F9C000, 0x5BB84C80, + 0xC3400000, 0x58380004, 0xCB420080, 0x00000000, 0x58380008, 0xCF400080, 0x5BFC0002, 0xB7E8FF90, + 0x00000000, 0xC3C00000, 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, + 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x58380008, 0xCF400420, 0x5838000A, 0xCF000000, 0x5BFC0002, + 0xB7E8FF90, 0x00000000, 0x00000000, 0xC3E02242, 0x5BFC0022, 0xC0004002, 0xCFC00000, 0x00000000, + 0xC121FFFE, 0x5911FE14, 0x15000000, 0x80000518, 0x00000000, 0x80002118, 0x00000000, 0x8000FFC8, + 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000, + 0xC000495C, 0xCAC40000, 0xC0004844, 0xC8840000, 0x46F90000, 0x8400FF6A, 0xC000487C, 0xC8040000, + 0x00000000, 0x00000000, 0x40080000, 0xCA000000, 0xC0001624, 0xCB040000, 0xA63C005A, 0x00000000, + 0x00000000, 0xA71EFF02, 0x00000000, 0xC0000824, 0xCA840000, 0x6CA08000, 0x6CA42000, 0x46610000, + 0x42290000, 0xC35E0002, 0xC6340068, 0xC0001624, 0xCF440080, 0xC2000000, 0xC161FFFE, 0x5955FFFE, + 0x15400000, 0x00000000, 0xC0004844, 0xC8840000, 0xC000082C, 0xCA040040, 0x00000000, 0x00000000, + 0x58880002, 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840040, 0x5AEC0002, 0xC000495C, + 0xCEC40000, 0x5E6C0006, 0x84000048, 0xC0004848, 0xCB840000, 0xC0000838, 0xC2500002, 0xCE440808, + 0x5FB80002, 0xC0004848, 0xCF840000, 0x5EEC0002, 0xC000495C, 0xCEC40000, 0x00000000, 0xC121FFFE, + 0x5911FE14, 0x15000000, 0x8000FD80, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, + 0xCC400000, 0xC0004960, 0xCAC40000, 0x00000000, 0x00000000, 0x5EEC0000, 0x840000F2, 0x00000000, + 0xB6FC0030, 0xC0001600, 0xCA040000, 0x00000000, 0x00000000, 0xA61E00B2, 0x6FE90000, 0xC0000A28, + 0xCE840808, 0xC2C00000, 0xC2800004, 0xB6E80080, 0xC0001604, 0xCA840000, 0xC0004960, 0xCEC40000, + 0xA69EFCA2, 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00002, 0xC0001600, 0xCA040000, + 0x00000000, 0x00000000, 0xA61E000A, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00000, 0xC0001604, + 0xCA840000, 0xC0004960, 0xCEC40000, 0xA69EFC0A, 0xC2400000, 0xC0000A14, 0xCA440030, 0x00000000, + 0x00000000, 0x46E52000, 0xA4400000, 0xC2800000, 0xDFEB0031, 0x8000FFF8, 0xDFEA0031, 0xB668FB82, + 0x00000000, 0xC00048A0, 0xCB040000, 0xC0000A10, 0xCA840000, 0x6F208000, 0x6F242000, 0x46610000, + 0x42A10000, 0xC2400000, 0xC0000A14, 0xCA440030, 0xC35E0002, 0xC6340068, 0xC0001604, 0xCF440080, + 0x5B300002, 0xB670FFF8, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF040000, 0xC0004960, 0xCEC40000, + 0x8000FAC0, 0xC0004918, 0xD2800000, 0xC2000000, 0xDF600040, 0x5E600080, 0x8400025A, 0x00000000, + 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000480A, 0xCA000000, 0xC0004912, 0xCA400000, + 0xC0004924, 0xCA800000, 0xC0004966, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, + 0x76610000, 0x76A10000, 0x76E10000, 0x840001B2, 0xC0004918, 0xCA400000, 0xC28001FE, 0x76A10000, + 0x5A640002, 0x6A254010, 0x5EE80000, 0x84000002, 0x6AA54000, 0x8000FFF8, 0xC6280000, 0x62818008, + 0xC0004918, 0xCF000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0004966, 0xCA400000, + 0xC2000002, 0x6A310000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, + 0x15000000, 0x6F346000, 0x4735A000, 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800080, 0xC2C00000, + 0x58340000, 0xCAC000E0, 0xC2400000, 0x5834000A, 0xCA420080, 0x6EA82000, 0x42E9E000, 0x6F2CA000, + 0x42E56000, 0x5AEC1400, 0xC3990040, 0xC7381C20, 0xC6F80068, 0x99005B78, 0xDB980000, 0xDBD80001, + 0x00000000, 0xDEA00000, 0x47210000, 0x8400FD68, 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002, + 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000, 0xC0004844, 0xC8840000, 0x5FB80000, 0x8400F7DA, + 0xC0001A1C, 0xCA000000, 0xC2400002, 0x6A452000, 0x76610000, 0x8400F7AA, 0xC000487C, 0xC8040000, + 0x00000000, 0x00000000, 0x40080000, 0xCA000000, 0xC4240000, 0x00000000, 0xA63C17BA, 0x00000000, + 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000, + 0x00000000, 0xC0004934, 0xCE000000, 0xC2800002, 0xC4681C10, 0xC62821D8, 0xC2600010, 0x5A650040, + 0xC0004800, 0xCB400000, 0xC2200400, 0x5A200000, 0xC7601048, 0xC0001220, 0xCE800000, 0xC0001200, + 0xCE400000, 0xC0001202, 0xCE000000, 0xC0001240, 0xCB400000, 0x00000000, 0x00000000, 0xA754FFC0, + 0xC2000000, 0xC7600048, 0xA7520022, 0x00000000, 0x00000000, 0x990062F0, 0xC0004822, 0xC9400000, + 0xC1800002, 0x80001668, 0x58204080, 0xC2000000, 0xCA000020, 0xC2400000, 0xCA414008, 0xC2800000, + 0xCA812008, 0xC2C00000, 0xCAC20020, 0xC0004938, 0xCE000000, 0xC0004920, 0xCE400000, 0xC0004916, + 0xCE800000, 0xC0004922, 0xCEC00000, 0xA6400520, 0x00000000, 0xC0004938, 0xCBC00000, 0x00000000, + 0xC3800000, 0x6FF48000, 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802018, 0x00000000, + 0xC2000000, 0x6FB46000, 0x47B5A000, 0x5B744C80, 0x5834000C, 0xCA000028, 0xC000491A, 0xCF800000, + 0x5E200000, 0x84000452, 0xC2000000, 0xDF610050, 0x5E6001E8, 0x8800FFD0, 0xC2000002, 0xC2400466, + 0xC2A00000, 0x5AA80000, 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000, + 0x990055B8, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC0004934, 0xCA400000, 0xC2000000, 0xC2800002, + 0x990055F8, 0xDA980000, 0xC6140000, 0xC6580000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, + 0x990056E0, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, + 0xC0004922, 0xCA001120, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE001120, 0xC0004932, 0xCBC000E0, + 0xC2800000, 0xC000491E, 0xCFC00000, 0xC0004862, 0xCA800068, 0xC3A0001A, 0x5BB94000, 0xC6B80068, + 0xC000491C, 0xCF800000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0x00000000, 0x00000000, + 0x00000000, 0xA8E2FFC8, 0xC2000000, 0xC1220002, 0xD90C0000, 0xDF600040, 0x5E600080, 0x8400FFDA, + 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, 0x99005B78, 0xDA180000, + 0xDA580001, 0x00000000, 0xC2000000, 0xDF610050, 0x5E6001FE, 0x8800FFD0, 0xC0004916, 0xCA800000, + 0xC2C00000, 0xDFEC0050, 0xC2400000, 0x46E52000, 0x84000032, 0x5EA80000, 0x84000022, 0xC2600002, + 0x990062F0, 0xC000482E, 0xC9400000, 0xC1800002, 0x80000018, 0xC2600000, 0x990062F0, 0xC000482C, + 0xC9400000, 0xC1800002, 0xC2000068, 0xC6240080, 0xC0004930, 0xCE400088, 0xC000491A, 0xC9800000, + 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x990059D8, 0xD9580000, 0xD9980001, + 0xD9D40000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xDF600040, 0x5E600080, + 0x8400FFD2, 0x00000000, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, + 0x99005B78, 0xDA180000, 0xDA580001, 0x00000000, 0x800010D0, 0x00000000, 0x990062F0, 0xC000482A, + 0xC9400000, 0xC1800002, 0x800010A0, 0xC0004938, 0xCBC00000, 0x00000000, 0x00000000, 0x6FF88000, + 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA000000, 0x00000000, 0x00000000, 0xA6000362, + 0x00000000, 0xC0004938, 0xCBC00000, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000, 0x4395C000, + 0x5BB84A00, 0x58380000, 0xCB002018, 0xC2000000, 0x58380008, 0xCA020080, 0x5838000C, 0xCAC00000, + 0x5838000E, 0xCA400000, 0xC000491A, 0xCF000000, 0xC0004930, 0xCEC00000, 0xC000493C, 0xCE000000, + 0xC0004932, 0xCE400000, 0x5E200000, 0x84000108, 0xC2800000, 0xA6FE009A, 0x6F206000, 0x47210000, + 0x5A204C80, 0x5820000C, 0xCA800028, 0x00000000, 0x00000000, 0x5EA80000, 0x840001DA, 0x00000000, + 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x990056E0, 0xC000491A, 0xC9400000, 0x00000000, + 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC0004930, 0xCAC00000, 0xC0004932, 0xCA400000, + 0xC7EC1120, 0xC0004930, 0xCEC00000, 0x5838000C, 0xCEC00000, 0x58000002, 0xCE400000, 0xC0004934, + 0xCA000000, 0xC2400002, 0x6E642000, 0x6E642000, 0x76252000, 0x84000012, 0xC2400002, 0x6E684000, + 0x58380008, 0xCE800208, 0xA6000000, 0x6E682000, 0x58380008, 0xCE800108, 0xC2400002, 0x6E642000, + 0x76252000, 0x840000D2, 0x58380008, 0xCA000000, 0xC2800000, 0xC2400000, 0xA60200A0, 0xDBA80000, + 0x6F386000, 0x4739C000, 0x5BB84C80, 0x58380004, 0xCA400080, 0x58380002, 0xCA800080, 0x00000000, + 0xDEB80000, 0x46694000, 0x88000048, 0x00000000, 0xC0004824, 0xCA000000, 0xC2400002, 0x6E640000, + 0x5A200002, 0xCE000000, 0x58380008, 0xCE400008, 0x80000000, 0x00000000, 0x80000030, 0xC0004934, + 0xCA000000, 0x00000000, 0x00000000, 0xA6020C4A, 0x00000000, 0x00000000, 0x80000C80, 0xC2800000, + 0xC2000200, 0xC240001A, 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFBA, 0xC2000006, 0xC2600982, + 0x5A643B6E, 0x5838000A, 0xCA800000, 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, + 0xCE800000, 0x990055B8, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC2000000, 0xC0004930, 0xCA02E010, + 0x58380026, 0xCA400000, 0x00000000, 0xC2800000, 0x990055F8, 0xDA980000, 0xC6140000, 0xC6580000, + 0xC0004934, 0xCA000000, 0x00000000, 0x00000000, 0xA6020002, 0x00000000, 0x00000000, 0x80000300, + 0xC0004938, 0xCBC00000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, + 0xCA000000, 0xC4240000, 0x00000000, 0x58240018, 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000, + 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000, 0xC62C0080, 0xC6270040, 0xC0004940, 0xCE400040, + 0xC6260040, 0xC0004942, 0xCE400040, 0xC000493C, 0xCA000000, 0x5EEC0000, 0x84000172, 0x5A6C0010, + 0x46614000, 0x88000178, 0x5A600052, 0x466D4000, 0x88000160, 0x58380006, 0xCA800000, 0xC0004940, + 0xCA000000, 0xC2400000, 0xC6A70040, 0x7E412000, 0x76252000, 0xC2000000, 0xC6A10040, 0x46610000, + 0x84000120, 0xC0004942, 0xCA000000, 0xC2400000, 0xC6A60040, 0x7E412000, 0x76252000, 0xC2000000, + 0xC6A00040, 0x58380002, 0xCA800000, 0x46610000, 0x840000D0, 0xC2400000, 0xC6A60080, 0x46E50000, + 0x880000C2, 0xC2400000, 0xC6A40080, 0x58380008, 0xCA800000, 0x466D0000, 0x880000A2, 0x00000000, + 0xA682FFF8, 0x00000000, 0xC7700B08, 0xA6840078, 0x00000000, 0xC7700A08, 0x80000068, 0xC7700208, + 0xC000493C, 0xCAC00000, 0x80000048, 0xC7700308, 0xC000493C, 0xCAC00000, 0x80000028, 0xC7700908, + 0x80000018, 0xC7700808, 0x80000008, 0xC7700708, 0x8000FFF8, 0xC7700508, 0xC0004944, 0xCF000000, + 0xC000493E, 0xCEC00000, 0xC0004938, 0xCA400000, 0xC000493C, 0xCB800000, 0xC000493E, 0xCB400000, + 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000, 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000080, + 0xC0004934, 0xCA000000, 0xC2400000, 0xC0004930, 0xCA42E010, 0xC3C00018, 0xA6020078, 0x00000000, + 0x43656000, 0x46F90000, 0x88000038, 0x47AD6000, 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00010, + 0x5E200000, 0x8400002A, 0x5BFC0002, 0x80000018, 0xC3C00004, 0x5A2C0008, 0x46390000, 0x8800FFFA, + 0x5FB80008, 0x6FE04000, 0x42390000, 0x46312000, 0x88000050, 0xC2400000, 0xC0004930, 0xCA42E010, + 0xC2060002, 0xC6800000, 0xCE000308, 0x6FE04000, 0x4631C000, 0x5F700010, 0x4675A000, 0xC2000000, + 0xC6340010, 0xC25A000A, 0xC000491A, 0xCA401C20, 0xC2800000, 0xC0004932, 0xCA8000E0, 0xC0004862, + 0xCA400068, 0x6FA04010, 0x42290000, 0xC000491E, 0xCE000000, 0xC7E41050, 0xC000491C, 0xCE400000, + 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF800000, 0xC000493E, 0xCF400000, 0xC000493A, 0xCFC00000, + 0x8000FFF0, 0x00000000, 0x00000000, 0x00000000, 0xC2000000, 0xDCE00000, 0xA622FFB8, 0xC1220002, + 0xD90C0000, 0xC0004938, 0xCBC00000, 0xC0004944, 0xCB400000, 0xC0004862, 0xCB000000, 0xC0004934, + 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xA6020248, 0xC2400000, 0x58380008, + 0xCA406008, 0xDFE80000, 0xC2218E08, 0x5A21BAF6, 0x46294000, 0x8400000A, 0xC2080002, 0x7235A000, + 0x80000040, 0x5E640000, 0x8400000A, 0xC20C0002, 0x7235A000, 0x80000018, 0xC2000000, 0xC760E718, + 0xC7604220, 0x5E200000, 0x8400025A, 0xC2200002, 0xC0004930, 0xCE001008, 0x990062F0, 0xC0004828, + 0xC9400000, 0xC1800002, 0x58380000, 0xCA000000, 0x00000000, 0x00000000, 0xA6000112, 0xC0004940, + 0xCA800000, 0xC0004942, 0xCA400000, 0xC7600080, 0xC6A01840, 0xC6601040, 0xC000493A, 0xCA400000, + 0xC0004934, 0xCA800000, 0xC0007200, 0x40300000, 0x40240000, 0x5C000004, 0x5EC07400, 0x8800FFFA, + 0x5C000200, 0xCE000000, 0x58000002, 0x5EC07400, 0x8800FFFA, 0x5C000200, 0xCE800000, 0xC000493E, + 0xCA000000, 0xC2400000, 0x5838000C, 0xCE400000, 0x990062F0, 0xC0004830, 0xC9400000, 0xC6180000, + 0xC0004930, 0xC6100080, 0xCD000080, 0x80000090, 0xC2400002, 0x58380008, 0xCE400008, 0xC0004944, + 0xCF400000, 0x80000260, 0xC000493C, 0xCA400000, 0xDFE80000, 0x5A300018, 0xC0007200, 0x40200000, + 0xCA000000, 0x58380008, 0xC6501080, 0xCD001080, 0x5838000A, 0xCE800000, 0x58380026, 0xCE000000, + 0xC0004944, 0xCF400000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0x80000020, 0x00000000, + 0x990062F0, 0xC0004826, 0xC9400000, 0xC1800002, 0x8000FDC0, 0xC2000000, 0xC2400080, 0xDF600040, + 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005B78, 0xDA580000, 0xDA980001, + 0x00000000, 0xC0004934, 0xCA000000, 0x00000000, 0xC2800000, 0xA6020140, 0xC2400004, 0xC2000200, + 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFC2, 0x00000000, 0xC000491A, 0xC9800000, 0xC0004862, + 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x990059D8, 0xD9580000, 0xD9980001, 0xD9D40000, + 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xC2400080, 0xDF600040, 0xB624FFCA, + 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005B78, 0xDA580000, 0xDA980001, 0x00000000, + 0x58380008, 0xCA400000, 0xC2000000, 0xCE000020, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE001080, 0x5838000A, + 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0000838, 0xC2500002, 0xCE440808, + 0xC0004848, 0xCB840000, 0xC2000000, 0xC000082C, 0xCA040030, 0x5FB80002, 0xC0004848, 0xCF840000, + 0x58880002, 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840000, 0x00000000, 0xC121FFFE, + 0x5911FE14, 0x15000000, 0x8000DEC0, 0xC2000000, 0xDF600040, 0x5E200080, 0x84000252, 0x00000000, + 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000480C, 0xCA000000, 0xC0004910, 0xCA400000, + 0xC000492C, 0xCA800000, 0xC0004968, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, + 0x76610000, 0x76A10000, 0x762D6000, 0x840001AA, 0xC0004926, 0xCA400000, 0xC201FFFE, 0x762D6000, + 0x5A640002, 0x6AE50010, 0x5F200000, 0x84000002, 0x6A250000, 0x8000FFF8, 0xC6E00000, 0x62014008, + 0xC0004926, 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0004968, 0xCA400000, + 0xC2000002, 0x6A290000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, + 0x15000000, 0x6EB4A000, 0x6E944000, 0x4575A000, 0x46B5A000, 0x5B744E20, 0x58340002, 0xC2000000, + 0xCA0000E0, 0x5834002E, 0xC2400000, 0xCA400080, 0x6EB0A000, 0x6EBC4000, 0x47F18000, 0x46B18000, + 0x5B300E4E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380068, 0xC6B81C20, 0x99005B78, + 0xDB980000, 0xDBD80001, 0x00000000, 0xC2000000, 0xDF600040, 0x5E200080, 0x8400033A, 0x00000000, + 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA000000, 0xC00049A0, 0xCA800000, + 0xC000492A, 0xCA400000, 0xC000496A, 0xCB000000, 0xC0004956, 0xCAC00000, 0x00000000, 0xC121FFFE, + 0x5911FE14, 0x15000000, 0x76318000, 0x76718000, 0x76B18000, 0x84000282, 0xC201FFFE, 0x76318000, + 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x84000002, 0x6A2D0000, 0x8000FFF8, 0xC7200000, 0x62016008, + 0xC0004956, 0xCEC00000, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000, 0x5B744E20, 0x58340000, + 0xC9C00000, 0xC00049A0, 0xCA000000, 0xC3000000, 0xC5F04020, 0xC2400000, 0xC5E50040, 0x7E412000, + 0x76610000, 0xCE000000, 0xC0004980, 0x40300000, 0xCEC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000, + 0x00000000, 0xC000496A, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000, + 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000, + 0x5B744E20, 0x5834000E, 0xC2000000, 0xCA0000E0, 0x58340008, 0xC2400000, 0xCA420080, 0x5834000C, + 0xC2800000, 0xCA832018, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008, 0xCB809020, + 0x58340008, 0xC2800000, 0xCA810018, 0x6EE0A000, 0x6EE44000, 0x46610000, 0x46E10000, 0x5A200008, + 0x5A200E28, 0x42290000, 0xC6380068, 0xC6F81C20, 0x99005B78, 0xDB980000, 0xDBD80001, 0x00000000, + 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0001A1C, 0xCA000000, + 0xC2400008, 0x6A452000, 0x76610000, 0x84000EAA, 0xC0000A28, 0xC3800000, 0xCB840030, 0xC0000A14, + 0xC3400000, 0xCB440030, 0xC0004880, 0xCB040000, 0xB7B40052, 0x58041802, 0xCAC00000, 0xA7000058, + 0x00000000, 0x00000000, 0xA6C8D7E8, 0xC1000000, 0xC6D00020, 0xC0004980, 0x40100000, 0xCA800000, + 0x80000058, 0x00000000, 0x00000000, 0x00000000, 0x8000D7A0, 0x00000000, 0xC2800000, 0xC7282020, + 0xC000490E, 0xCA400000, 0x6BE9E000, 0x00000000, 0x77E52000, 0x8400D758, 0x6EA0A000, 0x6E944000, + 0x45610000, 0x46A10000, 0x5A204E20, 0x5820000C, 0xCA000000, 0xC0004946, 0xCE800000, 0xA6220388, + 0x00000000, 0xC2200060, 0xC0004948, 0xCE000010, 0xCE001040, 0xC240000A, 0xC000494A, 0xCE400000, + 0xC2B60002, 0xC0004964, 0xCE801B08, 0x99005E48, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946, + 0xCBC00000, 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, + 0x99005C08, 0xDBD80000, 0xDB980001, 0x00000000, 0x99005950, 0xC000491C, 0xC1400000, 0xC9420050, + 0xC000491C, 0x99005E00, 0xC9400001, 0xC9800000, 0x00000000, 0x99005B78, 0xD9580000, 0xD9980001, + 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x99005840, 0xDBD80000, 0xDB980001, + 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, + 0x47F9C000, 0x5BB84E20, 0x58380010, 0xCA000000, 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000, + 0x44908000, 0x40100000, 0xCA400000, 0xC4340000, 0x00000000, 0xC7400000, 0xCE000000, 0xC161FFFE, + 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, + 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x990062F0, 0xC0004836, 0xC9400000, + 0xC1800002, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFC8, 0x00000000, 0x58380000, 0xC9000000, + 0xC00049A0, 0xCA000000, 0xC2800000, 0xC5290040, 0x72A10000, 0xCE000000, 0xC1220002, 0xD90C0000, + 0xC2000000, 0xC0000A14, 0xCA040030, 0xC0000A28, 0xC2500002, 0xCE440808, 0x58880002, 0xB608FFF8, + 0xC00048A0, 0xC0800000, 0xCC840000, 0x8000D368, 0xC0004946, 0xCBC00000, 0xC161FFFE, 0x5955FFFE, + 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000, + 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, + 0x5BB84E20, 0x58380008, 0xCA000000, 0x5838000C, 0xCA400000, 0xC3400000, 0xC6340008, 0xC000494E, + 0xCF400000, 0xC2800000, 0xC62A0080, 0xC3000000, 0xC6308020, 0x6F304000, 0x43298000, 0xC000493C, + 0xCF000000, 0xC2C00000, 0xC66C0080, 0xC0004950, 0xCEC00000, 0xC2800000, 0xC66AE028, 0xC0004954, + 0xCE800000, 0x5F740000, 0x84000188, 0x5E300028, 0x462D2000, 0x84000152, 0x462D2000, 0x8800011A, + 0x5E300018, 0x462D2000, 0x88000012, 0x462D2000, 0x8400002A, 0x00000000, 0x800000A8, 0x00000000, + 0x99005F88, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC3400002, 0xC000494E, 0xCF400000, 0xC161FFFE, + 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x7E814000, + 0x76A52000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC2200060, 0xC0004948, + 0xCE001040, 0xC2000000, 0xC000494C, 0xCE000000, 0x80000068, 0x00000000, 0x99005F88, 0xDBD80000, + 0xDB980001, 0xC7800000, 0x99006188, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC2200058, 0xC0004948, + 0xCE001040, 0xC2000002, 0xC000494C, 0xCE000000, 0xC2000006, 0xC0001006, 0xCE000000, 0x5838000A, + 0xCA400000, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE000000, 0xC000100A, 0xCE400000, 0xC0004954, + 0xCA800000, 0xC200000C, 0xC000494A, 0xCE000000, 0xC0004948, 0xCE800010, 0xC2B60000, 0xC0004964, + 0xCE800000, 0x99005E48, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946, 0xCBC00000, 0xC000494C, + 0xCA000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x5E200000, 0x840000E2, + 0x00000000, 0x99005C08, 0xDBD80000, 0xDB980001, 0x00000000, 0x99005950, 0xC000491C, 0xC1400000, + 0xC9420050, 0xC000491C, 0x99005E00, 0xC9400001, 0xC9800000, 0x00000000, 0x99005B78, 0xD9580000, + 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x99005840, 0xDBD80000, + 0xDB980001, 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, 0xC000493C, 0xCA800000, + 0xC000494E, 0xCAC00000, 0xC3000018, 0xC3400006, 0x5E200000, 0x84000012, 0xC2800000, 0xC2C00000, + 0xC300001E, 0xC3400000, 0xC6AC1080, 0xC72C0420, 0xC76C0818, 0x58380010, 0xCA800000, 0x58380008, + 0xCEC00000, 0xC6280108, 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, + 0xCB000000, 0xC4340000, 0x00000000, 0xC7400000, 0xCE800000, 0xC0004952, 0xCE800000, 0x00000000, + 0x00000000, 0x00000000, 0xA8E2FFC8, 0x00000000, 0xC000494C, 0xCA000000, 0xC0004950, 0xCAC00000, + 0x5E200000, 0x84000052, 0xDFE80000, 0x7E814000, 0x5834001A, 0xCE800000, 0x990062F0, 0xC0004834, + 0xC9400000, 0xC1800002, 0x990062F0, 0xC0004838, 0xC9400000, 0xC6D80000, 0xC1220002, 0xD90C0000, + 0x5E200000, 0x84000028, 0x5838002C, 0xCB000000, 0xDFE80000, 0x00000000, 0x58380014, 0xCF000000, + 0x80000040, 0xC2A1FFFE, 0x5AA9FFFE, 0x58380000, 0xC9000000, 0xC00049A0, 0xCB000000, 0xC2C00000, + 0xC52D0040, 0x72F18000, 0xCF000000, 0x5838000A, 0xCE800000, 0xC3000000, 0xC0000A14, 0xCB040030, + 0xC2D00002, 0xC0000A28, 0xCEC40808, 0xC000494E, 0xCA800000, 0x58880002, 0xB4B0FFF8, 0xC00048A0, + 0xC0800000, 0xCC840000, 0x5EA80000, 0x84000162, 0x5E200000, 0x84000150, 0xC000493C, 0xCA800000, + 0x00000000, 0x00000000, 0x5AA80060, 0xCE800000, 0x99005F88, 0xDBD80000, 0xDB980001, 0xC7800000, + 0x99006188, 0xDBD80000, 0xDB980001, 0xC7800000, 0x58380000, 0xCAC00000, 0x00000000, 0xC2000000, + 0xC6E04020, 0xC0004952, 0xCAC00000, 0x58380000, 0xCA800000, 0xC30C0002, 0xC6300020, 0xA6800078, + 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0001800, 0xCA000000, + 0x00000000, 0x00000000, 0xA60CFFCA, 0xC6F00508, 0xC6B0C408, 0xCF000000, 0x00000000, 0xC121FFFE, + 0x5911FE14, 0x15000000, 0x8000C9B0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000C948, + 0xDCBC0001, 0x5FFC0000, 0x8400003A, 0xC3800002, 0xDB880001, 0x5FFC0004, 0x8400C27A, 0xC3800000, + 0xDB880001, 0xC3CE0002, 0xC0000800, 0xCFC00708, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, + 0x00000000, 0x00000000, 0x00000000, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, + 0xCBC00000, 0xC4380000, 0x00000000, 0xC000480E, 0xCA000000, 0xC0004858, 0xCB440000, 0x00000000, + 0x00000000, 0x46350000, 0x88000098, 0x00000000, 0xA7C00028, 0xC0004854, 0xC1000002, 0xCD040000, + 0xC11C0000, 0xC000082C, 0xCD040E08, 0x800000C0, 0x00000000, 0xA7D20118, 0x00000000, 0xC7E14048, + 0xC2400000, 0xC6246030, 0xC200006A, 0x46610000, 0xC6240038, 0xC0000810, 0xCE440038, 0x8000FF58, + 0xC2000000, 0xC0000808, 0xCA040018, 0xC11C0000, 0xC000082C, 0xCD040E08, 0x5A200002, 0x5E600010, + 0x8400FFF8, 0xC2000000, 0xC0000808, 0xCE040018, 0xC3400000, 0x80000010, 0xC1200002, 0xC0000818, + 0xCD041008, 0x5B740002, 0xC0004858, 0xCF440000, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000, + 0xC11C0002, 0xC000082C, 0xCD040E08, 0x800005E8, 0x5B740002, 0xC0004858, 0xCF440000, 0xC7800000, + 0xC13C0002, 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, + 0xC0004848, 0xCD440000, 0x58880002, 0xB4980560, 0x00000000, 0xC0800000, 0x80000550, 0xC000487C, + 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000, 0xA7C00110, + 0xC000484C, 0xCA040000, 0xC2400000, 0xC0001AEC, 0xCA440020, 0x5A200002, 0xC000484C, 0xCE040000, + 0xB624006A, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, + 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002, 0xB4980450, 0x00000000, 0xC0800000, + 0x80000440, 0xC0004854, 0xC1000004, 0xCD040000, 0xC0000820, 0xC2000002, 0xCE040000, 0xC2000000, + 0xC000484C, 0xCE040000, 0xC0004858, 0xCE040000, 0x8000FF10, 0xC0004854, 0xC1000000, 0xCD040000, + 0xC11C0000, 0xC000082C, 0xCD040E08, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000, 0xC1200000, + 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC2000000, 0xC000484C, 0xCE040000, + 0x80000340, 0xC0001AC0, 0xCB840000, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, + 0xCBC00000, 0xC4280000, 0x00000000, 0x00000000, 0xC6800000, 0xC13C0000, 0xCD001E08, 0xA780022A, + 0x00000000, 0x00000000, 0xA7C001EA, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE040310, 0xA7E801A2, + 0x00000000, 0xC0004850, 0xCA040000, 0xC2400000, 0xC0001AEC, 0xCA448020, 0x5A200002, 0xC0004850, + 0xCE040000, 0xB624008A, 0x00000000, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC0001ACC, 0xC2000002, + 0xCE040008, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848, + 0xCD440000, 0x58880002, 0xB49801A8, 0x00000000, 0xC0800000, 0x80000198, 0xC0004854, 0xC1000000, + 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0x99005590, 0xC0004848, 0xC9440000, 0xC1800000, + 0xC2000000, 0xC0000820, 0xCE040000, 0xC1200000, 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, + 0xCD040E08, 0xC0004850, 0xCE040000, 0xC2000002, 0xC0001ACC, 0xCE040010, 0x800000D0, 0xC2000002, + 0xC0004850, 0xCE040000, 0x8000FE70, 0xC2000000, 0xC0004850, 0xCE040000, 0xA7E60012, 0x00000000, + 0xC2000002, 0xC0001B00, 0xCE040008, 0x8000FE58, 0x00000000, 0xA7860032, 0x00000000, 0xC6800000, + 0xC13C0002, 0xCD001E08, 0xC2020002, 0xC7E2A548, 0xC0001B00, 0xCE040000, 0x8000FE00, 0xC2040002, + 0xC0001B00, 0xCE040208, 0x8000FDE0, 0xC2C80002, 0x6AC56000, 0xDACC0000, 0xC0004854, 0xCB440000, + 0xC0004848, 0xCB840000, 0xC0000838, 0xC3C00000, 0xCBC40030, 0x5EF40004, 0x8400000A, 0xC3000000, + 0xC0001ACC, 0xCF040108, 0x47BD8000, 0x84000012, 0x47BD8000, 0x88000018, 0xC1006E8C, 0x8000B6B0, + 0xC0004840, 0xCC840000, 0x8000F698, 0xC0001AC0, 0xCAC40000, 0xC0004854, 0xCB440000, 0xA6C0FBB2, + 0x00000000, 0x5EF40000, 0x8400F6F2, 0x5EF40002, 0x8400F982, 0x5EF40004, 0x8400FB82, 0xC1006CE8, + 0x8000B628, 0x00000000, 0xC0800000, 0xDF4B0040, 0xC0004900, 0xCB800000, 0xC2000000, 0xC000490A, + 0xA78000B0, 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002, 0xD90C0000, 0x6FF46000, 0x47F5A000, + 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400080, 0xC0004900, 0xCE000008, 0x5A640002, 0x58340004, + 0xC6500080, 0xCD000080, 0xC0004914, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, + 0xC0000408, 0xCE000000, 0xA78200B8, 0xC0004908, 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002, + 0xD90C0000, 0x6FF4A000, 0x6FD44000, 0x4575A000, 0x47F5A000, 0x5B744E20, 0xC2800000, 0x58340006, + 0xCA800080, 0xC2000000, 0xC0004900, 0xCE000108, 0x5EA80002, 0x58340006, 0xC6900080, 0xCD000080, + 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408, 0xCE000000, 0xDCA80001, 0x5EA80000, 0x8400B498, + 0x00000000, 0xA4800210, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00020, 0xC3400000, 0xC2400000, + 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0x58380008, 0xCB400080, 0x58380006, 0xCA400080, 0x5F740002, + 0x58380008, 0xC7500080, 0xCD000080, 0xC2000000, 0x58380004, 0xCA020080, 0xC3000000, 0x5838000C, + 0xCB000028, 0x5A640002, 0x46250000, 0x8400FFF8, 0xC2400000, 0x58380006, 0xC6500080, 0xCD000080, + 0xC2000000, 0x5838000A, 0xCA020080, 0x5B300002, 0x5838000C, 0xC7100028, 0xCD000028, 0xC2420020, + 0x5A200004, 0x46612000, 0x8400FFF8, 0xC2000000, 0x5838000A, 0xC6101080, 0xCD001080, 0xC0004966, + 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0x5F740000, 0x84000028, 0xC0004912, + 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x5F300020, 0x84000028, + 0xC0004924, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4820050, + 0xC2400000, 0xC000140E, 0xCA408020, 0xC2000002, 0xC0004900, 0xCE000008, 0xC000490A, 0xCE400000, + 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA4840250, 0x00000000, 0xC3C00000, + 0xC000140E, 0xCBC10020, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, + 0x5BB84E20, 0x5838002E, 0xCA800080, 0x58380006, 0xCA020080, 0xC3400000, 0x5838002E, 0xCB420080, + 0x5AA80002, 0x46290000, 0x8400FFF8, 0xC2800000, 0x5838002E, 0xC6900080, 0xCD000080, 0x5F740002, + 0x5838002E, 0xC7501080, 0xCD001080, 0xC0004968, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, + 0xCE400000, 0xC000492A, 0xCA800000, 0x5E740000, 0x84000028, 0xC0004910, 0xCA000000, 0xC2C00002, + 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x6ABD4010, 0xA680009A, 0x00000000, 0x58380032, + 0xCA000000, 0x58000002, 0xCA400000, 0x5838000C, 0x00000000, 0xCE000001, 0xCE400000, 0xC000492A, + 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x72E10000, 0xCE000000, 0xC000492C, 0xCA000000, 0xC2C00002, + 0x6AFD6000, 0x72E10000, 0xCE000000, 0x80000028, 0xC000492C, 0xCA000000, 0xC2C00002, 0x6AFD6000, + 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4880128, 0xC2C00000, 0xC000140E, 0xCAC20020, 0xC000490E, + 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000, 0xC000496A, 0xCA400000, + 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0x6EF0A000, 0x6ED44000, 0x45718000, 0x46F18000, + 0x5B304E20, 0x58300000, 0xCA000000, 0x00000000, 0xC2400002, 0x76252000, 0x8400005A, 0x58300000, + 0xCA400000, 0xC2800000, 0x00000000, 0xC6684020, 0xC24C0002, 0xC6A40020, 0xC624C408, 0x58300010, + 0xCA400508, 0x00000000, 0xC0001800, 0xCE400000, 0xA4860050, 0xC2400000, 0xC000140E, 0xCA418020, + 0xC2020002, 0xC0004900, 0xCE000108, 0xC0004908, 0xCE400000, 0xC1000000, 0xD9000001, 0xD8400080, + 0xC1000004, 0xD9000001, 0xC0001408, 0xCC800000, 0xC10E0002, 0xD90C0000, 0x8000ED98, 0xDFBC0001, + 0xC000496E, 0x99006298, 0xC9400000, 0xC7D80000, 0x00000000, 0xC5700000, 0x5EF00020, 0x88000130, + 0x6F346000, 0x4735A000, 0x5B744C80, 0x58340008, 0xC2400000, 0xCA400080, 0x00000000, 0xC2000000, + 0x5A640002, 0xCE400080, 0x58340004, 0xCA000080, 0x00000000, 0x00000000, 0x5E200002, 0xCE000080, + 0xC0004912, 0xCA800000, 0xC2400002, 0x6A712000, 0x72694000, 0xCE800000, 0x5E200000, 0x8400003A, + 0xC000480A, 0xCA000000, 0xC0000408, 0xCA800000, 0x76610000, 0x00000000, 0x72294000, 0xCE800000, + 0x80000020, 0xC0004914, 0xCA000000, 0x7E412000, 0x00000000, 0x76610000, 0xCE000000, 0x800000B8, + 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000, 0x5B744E20, 0x5834002E, 0xC2400000, 0xCA420080, + 0x00000000, 0xC2000000, 0x5A640002, 0xC6501080, 0xCD001080, 0x58340006, 0xCA000080, 0x00000000, + 0x00000000, 0x5A200002, 0xCE000080, 0xC0004910, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x72252000, + 0xCE400000, 0xC2000002, 0x6A310000, 0xC000042A, 0xCE000000, 0xC1040002, 0xD90C0000, 0x00000000, + 0x8000EB08, 0x00000000, 0xC4980930, 0x9D000000, 0xC5580030, 0xC0000838, 0xCD840000, 0xC1440200, + 0xC1C03200, 0xC55C1078, 0xC000100E, 0x9D000000, 0xCD800000, 0xC000100C, 0xCDC00000, 0xC0004862, + 0xC9C00000, 0x00000000, 0x00000000, 0xD9D80001, 0xC0007200, 0x401C0000, 0x5DC07400, 0x8800FFFA, + 0x5C000200, 0xCD800000, 0xC1F0000A, 0x71D4A000, 0xDD980000, 0xDD9C0001, 0x41D8E000, 0xC5D40268, + 0xC0001010, 0xCD400000, 0x6C9C8000, 0x449CE000, 0x449CE000, 0x59DC0004, 0xC1601260, 0xC5D40268, + 0x9D000000, 0xC0001012, 0xCD400000, 0x00000000, 0x00000000, 0xD9580000, 0x6D586000, 0x4558C000, + 0x59984C80, 0xD9980001, 0x5818000A, 0xC1800000, 0xC9800080, 0xC0005400, 0x6D5CA000, 0x401C0000, + 0x40180000, 0xC9400000, 0x58000002, 0x00000000, 0xC9C00000, 0xC0004930, 0xCD400000, 0xC0004932, + 0xCDC00000, 0x59980004, 0xC1C20020, 0xB59CFFF8, 0x00000000, 0xC1800000, 0xDD9C0001, 0x581C000A, + 0xCD800080, 0x581C000C, 0xC1800000, 0xC9800028, 0xC1C00002, 0xDD940000, 0x69D4E000, 0x5D980002, + 0xCD800028, 0xC0004924, 0xC9800000, 0x00000000, 0x9D000000, 0x00000000, 0x71D8C000, 0xCD800000, + 0xC000492A, 0xC9400000, 0xC1C00002, 0x69D8E000, 0x7DC0C000, 0x7594A000, 0xCD400000, 0xC000492C, + 0xC9400000, 0xDD800001, 0x58000032, 0x75D4A000, 0x84000078, 0xC9400001, 0xC9800000, 0xDD800001, + 0x5800000C, 0x00000000, 0xCD400001, 0xCD800000, 0xC000492C, 0xC9400000, 0xC000492A, 0xC9800000, + 0x71D4A000, 0xC000492C, 0xCD400000, 0x71D8C000, 0xC000492A, 0xCD800000, 0x9D000000, 0x00000000, + 0x00000000, 0x00000000, 0xC0004862, 0xC9800000, 0x00000000, 0xC1C00200, 0x4194C000, 0x45D8E000, + 0x8800FFFA, 0xC5D80000, 0xC0004862, 0xCD800000, 0xC0001406, 0xC9800000, 0xC1C00002, 0x9D000000, + 0xC5D80A08, 0xC5581050, 0xCD800000, 0xC0004930, 0xC9800000, 0xC0004932, 0xC9C00000, 0xC140000E, + 0xC5581C20, 0xDD940000, 0xC0007200, 0x40140000, 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCD800000, + 0x58000002, 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCDC00000, 0xDD540000, 0xC1C00000, 0x58140006, + 0xC9C20080, 0xC1800000, 0x58140000, 0xC98000E0, 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC00000, + 0xDD980000, 0xC1C00022, 0xC5D80D78, 0xDD940001, 0xC5581C20, 0xC000491C, 0xCD800000, 0xDD540000, + 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000, 0x58140004, 0xC9820080, 0x00000000, 0x59DC0002, + 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000, 0x58140006, 0xC5D81080, 0xCD801080, 0xC0004860, + 0xC9400000, 0xC1820080, 0xC1D00002, 0x58146B00, 0xD5800000, 0x58000002, 0xD5800001, 0x59540004, + 0xB558FFF8, 0xC0004860, 0xC1400000, 0xCD400000, 0xDD980001, 0x9D000000, 0xDD940000, 0xC0001404, + 0xCDC00808, 0xC1C00000, 0xC1800200, 0x5D980004, 0xDF5D0050, 0x45D8A000, 0x8800FFDA, 0xDD800001, + 0x5800000C, 0x00000000, 0xC9400001, 0xC9800000, 0xC1C00002, 0xC5D43F08, 0xC5D81E08, 0xC0004862, + 0xC9C00000, 0x00000000, 0x00000000, 0x581C7200, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD400000, + 0x58000002, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0xC0004862, 0xC9C00000, 0x00000000, + 0xC15004C0, 0xC5D40068, 0xDD9C0000, 0xC5D41C20, 0xC1C00000, 0xDD800001, 0x58000030, 0xC9C00080, + 0xDD800001, 0x58000002, 0xC9800000, 0x6DDC2000, 0xC000491C, 0x41D8E000, 0xCD400001, 0xCDC00000, + 0xDD940001, 0xC1C00000, 0x58140030, 0xC9C00080, 0xC1800000, 0x58140006, 0xC9820080, 0x00000000, + 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000, 0x58140030, 0xC5D80080, 0xCD800080, + 0xC1C00000, 0xDF5C0040, 0x5DDC0080, 0x8400FFD2, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, + 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440068, 0xC1A0FFFE, 0x59980E28, 0xC000100C, 0xCD400000, + 0xC000100E, 0xCD800000, 0xC0004964, 0xC9800000, 0x00000000, 0xC170000A, 0x7194A000, 0x6C988000, + 0x4498C000, 0x4498C000, 0x59980004, 0xC5940278, 0xC0001010, 0xCD400000, 0xC0004946, 0xC9400000, + 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000, 0x45D8C000, 0x4558C000, 0xC000494A, 0xC9400000, + 0xC0004948, 0xC9C00000, 0x4194C000, 0xC1400012, 0xC55C1820, 0x9D000000, 0xC59C0270, 0xC0001012, + 0xCDC00000, 0xC1400000, 0x58000012, 0xC9410040, 0xC0004950, 0xC9C00000, 0xC5580000, 0xC5940840, + 0xC5581080, 0xD9940000, 0xC000493C, 0xC9400000, 0xC0004954, 0xC9800000, 0x59DC00A8, 0x455CE000, + 0x41D8E000, 0x5D5C0030, 0x8800FFF8, 0xC1C00030, 0xC1800000, 0xC5D84030, 0xC1400000, 0xC5D40010, + 0x5DD40002, 0x8400005A, 0x5DD40004, 0x84000082, 0x5DD40006, 0x840000AA, 0x5DD80026, 0x840000D2, + 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400000, 0x59980002, 0x8000FFA8, 0xDD540000, + 0xDD800001, 0x58000008, 0x40180000, 0xCD4000C0, 0x59980002, 0x8000FF70, 0xDD540000, 0xDD800001, + 0x58000008, 0x40180000, 0xCD400080, 0x59980002, 0x8000FF38, 0xDD540000, 0xDD800001, 0x58000008, + 0x40180000, 0xCD400040, 0x59980002, 0x8000FF00, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, + 0x00000000, 0x58000012, 0xC9400000, 0xC0004954, 0xC9C00000, 0xC0004950, 0xC9400080, 0xDD800001, + 0x58000028, 0x5D9C0000, 0x8400003A, 0x5D9C0002, 0x8400003A, 0x5D9C0004, 0x84000052, 0xC55B0040, + 0xC55C08C0, 0xCD800041, 0xCDC008C0, 0x80000048, 0xCD400000, 0x80000038, 0xC55900C0, 0xC55C1840, + 0xCD8000C1, 0xCDC01840, 0x80000010, 0xC55A0080, 0xC55C1080, 0xCD800081, 0xCDC01080, 0x9D000000, + 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, + 0x8800FFFA, 0xC5940000, 0x9D000000, 0xCD400000, 0x00000000, 0x00000000, 0x9D000000, 0x4158A000, + 0xCD400000, 0x00000000, +}; + +static unsigned int firmware_binary_data[] = { +}; + + +#endif // IFXMIPS_ATM_FW_DANUBE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h new file mode 100644 index 0000000000..ff4e500d57 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_danube_retx.h @@ -0,0 +1,612 @@ +#ifndef IFXMIPS_ATM_FW_DANUBE_H
+#define IFXMIPS_ATM_FW_DANUBE_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_danube.h
+** PROJECT : Danube
+** MODULES : ATM (ADSL)
+**
+** DATE : 1 AUG 2005
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 4 AUG 2005 Xu Liang Initiate Version
+** 23 OCT 2006 Xu Liang Add GPL header.
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 15
+
+
+static unsigned int firmware_binary_code[] = {
+ 0x800004A0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFC8, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C0000, 0xC2000002, 0xDA080001, 0xC0001B50, 0x8C100000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC2000000, 0xDA080001, 0x80006018, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005FF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1001DA6, 0x8D3C0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80005EF0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC0004840, 0xC8840000, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC0004840, 0xC8840000, 0xC2001AEE, 0x8E100000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC80001, 0xC10C0002, 0xD90C0000, 0x8000FEC8, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C0000, 0xC0004808, 0xC8400000, 0xC2001B4C, 0x8E100000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3E02252, 0x5BFC001E, 0xC0004002, 0xCFC00000, 0xC3C00000,
+ 0xDBC80001, 0xC1400008, 0xC1900000, 0x71948000, 0x15000100, 0xC140000A, 0xC1900002, 0x71948000,
+ 0x15000100, 0xC140000C, 0xC1900004, 0x71948000, 0x15000100, 0xC1400004, 0xC1900006, 0x71948000,
+ 0x15000100, 0xC1400006, 0xC1900008, 0x71948000, 0x15000100, 0xC140000E, 0xC190000A, 0x71948000,
+ 0x15000100, 0xC1400000, 0xC190000C, 0x71948000, 0x15000100, 0xC1400002, 0xC190000E, 0x71948000,
+ 0x15000100, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC11C0002, 0xC000082C, 0xCD040E08,
+ 0xC0400002, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC0000824, 0x00000000, 0xCBC00001, 0xCB800001,
+ 0xCB400001, 0xCB000000, 0xC0004878, 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800001, 0x5B744000,
+ 0xCF400001, 0x5B304000, 0xCF000000, 0xC0000A10, 0x00000000, 0xCBC00001, 0xCB800000, 0xC0004874,
+ 0x5BFC4000, 0xCFC00001, 0x5BB84000, 0xCF800000, 0xC30001FE, 0xC000140A, 0xCF000000, 0xC3000000,
+ 0x7F018000, 0xC000042E, 0xCF000000, 0xC000040E, 0xCF000000, 0xC3C1FFFE, 0xC000490E, 0xCFC00080,
+ 0xC000492C, 0xCFC00080, 0xC0004924, 0xCFC00040, 0xC0004912, 0xCFC00040, 0xC0004966, 0xCFC00040,
+ 0xC0004968, 0xCFC00080, 0xC000496A, 0xCFC00080, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x5838000A, 0xCF000000, 0x5BFC0002, 0xB7E8FFA8,
+ 0x00000000, 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0xC3400000, 0x58380004,
+ 0xCB420080, 0x00000000, 0x58380008, 0xCF400080, 0x5BFC0002, 0xB7E8FF90, 0x00000000, 0xC3C00000,
+ 0xC2800020, 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x58380008, 0xCF400420, 0x5838000A, 0xCF000000, 0x5BFC0002, 0xB7E8FF90, 0x00000000,
+ 0x00000000, 0xC0004816, 0xC3C00000, 0xCBC00080, 0x00000000, 0x00000000, 0xC1000000, 0xD9040001,
+ 0xDBC40080, 0xC1000006, 0xD9040001, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0xC3C00000,
+ 0xDCFC2008, 0x5FFC0002, 0x00000000, 0x98C08D62, 0xC0004730, 0xC9400000, 0xC0004732, 0xC0001AF2,
+ 0xCBC00000, 0x00000000, 0x00000000, 0xA7C20450, 0xC000474A, 0xCA800000, 0x00000000, 0x00000000,
+ 0x5D280000, 0x8400FFC8, 0x00000000, 0xC121FFFE, 0x5911FEF4, 0x15000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2802000, 0x6EA8E010, 0xC0004200, 0xC2400000, 0x7E410000, 0xC1000000, 0xCE400001, 0xCE400001,
+ 0xCE400001, 0xCE400001, 0x5EA80002, 0x8400FFC0, 0xC0004300, 0xC2800200, 0x6EA84010, 0xCE400001,
+ 0xCE000001, 0xCE400001, 0xCE000001, 0xCE400001, 0xCE000001, 0xCE400001, 0xCE000001, 0x5EA80002,
+ 0x8400FFA0, 0xC0004700, 0xC2800200, 0x6EA8E010, 0xCE400001, 0xCE400001, 0xCE400001, 0xCE400001,
+ 0x5EA80002, 0x8400FFC0, 0xC0004740, 0xCE400000, 0xC0004742, 0xC1000200, 0x5D100002, 0xCD000000,
+ 0xC0004744, 0xCE400000, 0xC0004746, 0xCE400000, 0xC0004748, 0xCE400000, 0xC000474A, 0xCE400000,
+ 0xC000474C, 0xC1000002, 0xCD000000, 0xC000474E, 0xCE400000, 0xC0004750, 0xCE400000, 0xC0004752,
+ 0xCE400000, 0xC0004754, 0xCE400000, 0xC0400000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0xC0000838,
+ 0xCE400000, 0xC0000818, 0xCE400000, 0xC0000820, 0xCE400000, 0xC2804840, 0xC240485A, 0x98C086B0,
+ 0xC6800000, 0xC6540000, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD040E08, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0xC0000A10, 0xCB800000, 0xC0000A12, 0xCB400000, 0xC0000A14, 0xCB000000,
+ 0xC0000A16, 0xCAC00000, 0xC0000040, 0xC2800000, 0xCE800008, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC2800002,
+ 0xCE800008, 0xC0000A10, 0xCF800000, 0xC0000A12, 0xCF400000, 0xC0000A14, 0xCF000000, 0xC0000A16,
+ 0xCEC00000, 0xC1000000, 0xC00048A0, 0xCD000000, 0xC00048A2, 0xCD000000, 0xC0001AF2, 0xC1000000,
+ 0xCD000108, 0x80001020, 0x00000000, 0xC3C00000, 0xDCFC2008, 0x5FFC0002, 0x00000000, 0x98C08D62,
+ 0xC0004730, 0xC9400000, 0xC0004732, 0x800033C0, 0x00000000, 0xC3C00000, 0xDCFC2008, 0x5FFC0002,
+ 0x00000000, 0x98C08D62, 0xC0004730, 0xC9400000, 0xC0004732, 0xC0004810, 0xC9000000, 0xC000474A,
+ 0xC9400000, 0xA50007C8, 0x00000000, 0x5D140002, 0x840007BA, 0xC1000000, 0xC000484A, 0xC9000000,
+ 0xC0004740, 0xC8400000, 0x5D100000, 0x84000780, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FEF4,
+ 0x15000000, 0xC0004744, 0xC8800000, 0xC0001AF0, 0xC3000000, 0x58000002, 0xCB010040, 0x6C7C2000,
+ 0x5BFC4300, 0x98C08A88, 0xC1400000, 0xC4540028, 0x6C40A010, 0x5D240002, 0x84000202, 0x00000000,
+ 0xC0004742, 0xCA800000, 0x00000000, 0x00000000, 0x59280002, 0x6D130000, 0x6D130010, 0x44508000,
+ 0x8400067A, 0x00000000, 0x98C08870, 0xC4540000, 0xC6980000, 0xC241FFFE, 0xC6740000, 0x5D35FFFE,
+ 0x8400063A, 0x44748000, 0x8400062A, 0xC1000000, 0x6F502000, 0xC0004300, 0x40100000, 0xC1400000,
+ 0x58000000, 0xC9410040, 0xC1800000, 0xC0004814, 0xC9820040, 0x4570A000, 0xC10001FE, 0x4150A004,
+ 0x45948000, 0x880005B2, 0x4474C000, 0xC1000200, 0x4190C004, 0xC000473E, 0xC9000000, 0x00000000,
+ 0x00000000, 0x41188000, 0xCD000000, 0xC000471C, 0xC9000000, 0x00000000, 0x00000000, 0x41188000,
+ 0xCD000000, 0x98C087E8, 0xC4540000, 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010,
+ 0x47448000, 0x8400FFA8, 0xC7440000, 0xC0004740, 0xCC400000, 0xC0800000, 0xC0004744, 0xCC800000,
+ 0x800004B8, 0xC1000000, 0x583C0000, 0xC9000040, 0x00000000, 0x00000000, 0x45088000, 0x88000268,
+ 0xC1400000, 0x583C0000, 0xC9410040, 0xC1800000, 0xC0004814, 0xC9800040, 0x4570A000, 0xC10001FE,
+ 0x4150A004, 0x45948000, 0x8800042A, 0xC3800000, 0x583C0002, 0xCB820080, 0xC1000000, 0x583C0002,
+ 0xC9000080, 0x00000000, 0x00000000, 0x45388000, 0x84000232, 0xC0400002, 0xC0800000, 0xC3C00000,
+ 0xC000481A, 0xC8000000, 0x6F908000, 0x47908000, 0x47908000, 0x4011E000, 0xC000491E, 0xCFC00000,
+ 0xC3400000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCAC00000,
+ 0xC4300000, 0x00000000, 0xC7340068, 0xC1000002, 0xC5341B08, 0xC100001C, 0xC5341050, 0xC100000C,
+ 0xC5340D18, 0xC000491C, 0xCF400000, 0xC3000000, 0xDF700040, 0x5D300080, 0x8800FFD0, 0xC000474A,
+ 0xC1000002, 0xCD000000, 0xC000491C, 0xCB400000, 0xC000491E, 0xCBC00000, 0x99007F18, 0xDB580000,
+ 0xDBD80001, 0x00000000, 0xC1400000, 0xC794A038, 0xC1800000, 0xC7980028, 0x58144200, 0xC9C00000,
+ 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x80000210, 0x00000000, 0xC1000000,
+ 0x583C0000, 0xC903E008, 0x00000000, 0x00000000, 0x5D100000, 0x8400002A, 0xC0004734, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800000A8, 0xC1400000, 0x583C0000, 0xC9410040,
+ 0xC1800000, 0xC0004814, 0xC9820040, 0x4570A000, 0xC10001FE, 0x4150A004, 0x45948000, 0x88000142,
+ 0xC000473E, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC000471C, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC3800000, 0x583C0002, 0xCB820080, 0x00000000,
+ 0x00000000, 0x5D39FFFE, 0x8400004A, 0xC1400000, 0xC794A038, 0xC1800000, 0xC7980028, 0x58144200,
+ 0xC9C00000, 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x98C087E8, 0xC4540000,
+ 0x6C58A010, 0xC0004700, 0x58440002, 0x6C470000, 0x6C470010, 0xC0004740, 0xCC400000, 0xC0800000,
+ 0xC0004744, 0xCC800000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000F270, 0x00000000,
+ 0x00000000, 0x98C086F0, 0xC0004748, 0xC9800000, 0xC2000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC1400000, 0xC7D4A038, 0xC1800000, 0xC7D80028, 0x58144200,
+ 0xC9C00000, 0xC1210000, 0x69188010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C087E8, 0xC7D40000, 0x6FD8A010, 0xC0004700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x98C08870, 0xC7D40000, 0xC7980000, 0xC241FFFE, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08A88, 0xC1400000, 0xC7D40028, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AB8, 0xC1400000, 0xC7D40028, 0x6FC0A010,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08AF0, 0xC7D40000, 0xC0004740, 0xC9C00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x98C08BE0, 0xC7D40000, 0xC0004742, 0xC9800000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004958, 0xC8400000, 0x00000000, 0xC3C00002,
+ 0x7BC42000, 0xCC400000, 0xC0004848, 0xCB840000, 0xC000495C, 0xCAC40000, 0xC0004844, 0xC8840000,
+ 0x46F90000, 0x8400F47A, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCA000000,
+ 0xC0001624, 0xCB040000, 0xA63C005A, 0x00000000, 0x00000000, 0xA71EF412, 0x00000000, 0xC0000824,
+ 0xCA840000, 0x6CA08000, 0x6CA42000, 0x46610000, 0x42290000, 0xC35E0002, 0xC6340068, 0xC0001624,
+ 0xCF440080, 0xC2000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xC0004844, 0xC8840000, 0xC000082C, 0xCA040040, 0x00000000, 0x00000000, 0x58880002,
+ 0xB608FFF8, 0x00000000, 0xC0800000, 0xC0004844, 0xCC840040, 0x5AEC0002, 0xC000495C, 0xCEC40000,
+ 0x5E6C0006, 0x84000048, 0xC0004848, 0xCB840000, 0xC0000838, 0xC2500002, 0xCE440808, 0x5FB80002,
+ 0xC0004848, 0xCF840000, 0x5EEC0002, 0xC000495C, 0xCEC40000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0x8000F278, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000,
+ 0xC0004960, 0xCAC40000, 0x00000000, 0x00000000, 0x5EEC0000, 0x840000F2, 0x00000000, 0xB6FC0030,
+ 0xC0001600, 0xCA040000, 0x00000000, 0x00000000, 0xA61E00B2, 0x6FE90000, 0xC0000A28, 0xCE840808,
+ 0xC2C00000, 0xC2800004, 0xB6E80080, 0xC0001604, 0xCA840000, 0xC0004960, 0xCEC40000, 0xA69EFC8A,
+ 0x00000000, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00002, 0xC0001600, 0xCA040000, 0x00000000,
+ 0x00000000, 0xA61E000A, 0x6FE90000, 0xC0000A28, 0xCE840808, 0xC2C00000, 0xC0001604, 0xCA840000,
+ 0xC0004960, 0xCEC40000, 0xA69EFBF2, 0xC2400000, 0xC0000A14, 0xCA440030, 0x00000000, 0x00000000,
+ 0x46E52000, 0xA4400000, 0xC2800000, 0xDFEB0031, 0x8000FFF8, 0xDFEA0031, 0xB668EBEA, 0x00000000,
+ 0xC00048A0, 0xCB040000, 0xC0000A10, 0xCA840000, 0x6F208000, 0x6F242000, 0x46610000, 0x42A10000,
+ 0xC2400000, 0xC0000A14, 0xCA440030, 0xC35E0002, 0xC6340068, 0xC0001604, 0xCF440080, 0x5B300002,
+ 0xB670FFF8, 0x5AEC0002, 0xC3000000, 0xC00048A0, 0xCF040000, 0xC0004960, 0xCEC40000, 0x8000F018,
+ 0xC0004918, 0xD2800000, 0xC2000000, 0xDF600040, 0x5E600080, 0x8400028A, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000480A, 0xCA000000,
+ 0xC0004912, 0xCA400000, 0xC0004924, 0xCA800000, 0xC0004966, 0xCAC00000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x76610000, 0x76A10000, 0x76E10000, 0x840001CA, 0xC0004918, 0xCA400000,
+ 0xC28001FE, 0x76A10000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x84000002, 0x6AA54000, 0x8000FFF8,
+ 0xC6280000, 0x62818008, 0xC0004918, 0xCF000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC0004966, 0xCA400000, 0xC2000002, 0x6A310000, 0x7E010000,
+ 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6F346000, 0x4735A000,
+ 0x5B744C80, 0xC2800000, 0x58340006, 0xCA800080, 0xC2C00000, 0x58340000, 0xCAC000E0, 0xC2400000,
+ 0x5834000A, 0xCA420080, 0x6EA82000, 0x42E9E000, 0x6F2CA000, 0x42E56000, 0x5AEC1400, 0xC3990040,
+ 0xC7381C20, 0xC6F80068, 0x99007F18, 0xDB980000, 0xDBD80001, 0x00000000, 0xDEA00000, 0x47210000,
+ 0x8400FD38, 0xC0004958, 0xC8400000, 0x00000000, 0xC1000002, 0x79042000, 0xCC400000, 0xC0004848,
+ 0xCBC40000, 0xC0004844, 0xC8840000, 0x5FFC0000, 0x8400ECA2, 0xC0004740, 0xCB000000, 0xC0004744,
+ 0xCAC00000, 0x6F282000, 0x5AA84300, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000,
+ 0xCA400000, 0xC4000000, 0x00000000, 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000,
+ 0x40100000, 0xC9000000, 0xC4340000, 0x00000000, 0x5C440000, 0x8400008A, 0x00000000, 0xC00047D2,
+ 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x58340002, 0xC9000080, 0x00000000,
+ 0x00000000, 0x58280002, 0x6D120000, 0xCD001080, 0x5AEC0002, 0xC0004744, 0xCEC00000, 0x80000618,
+ 0x00000000, 0xC00047C0, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xA67C0028,
+ 0xC00047C2, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80001E00, 0x00000000,
+ 0xA6600022, 0xC00047C4, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000558,
+ 0xC00047C6, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC3C00000, 0xC67D0040,
+ 0xC3800000, 0xC6780040, 0x473C8000, 0x84000090, 0x46F88000, 0x84000080, 0xC1000000, 0xC0004814,
+ 0xC9000040, 0x00000000, 0x00000000, 0x5D100000, 0x840000D8, 0x5AEC0002, 0xC0004744, 0xCEC00000,
+ 0xC00047CA, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000460, 0x00000000,
+ 0x98C08AF0, 0xC7D40000, 0xC0004740, 0xC9C00000, 0x5D240000, 0x84000052, 0x00000000, 0x98C087E8,
+ 0xC7D40000, 0x6FD8A010, 0xC0004700, 0xC00047C8, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0x80001C28, 0xC00047CC, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x6FE82000, 0x5AA84300, 0x5D380000, 0x84000088, 0x00000000, 0x98C086F0, 0xC0004748, 0xC9800000,
+ 0xC2000000, 0x58280002, 0x6E520000, 0xCD001080, 0x58280002, 0xCE400080, 0x5D25FFFE, 0x84000028,
+ 0xC00047D0, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800002B8, 0xC3000000,
+ 0x58280002, 0xCB000080, 0x00000000, 0x00000000, 0x5D31FFFE, 0x84000030, 0xC00047D0, 0xC9000000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000248, 0x00000000, 0x98C086F0, 0xC0004748,
+ 0xC9800000, 0xC2000000, 0x58340002, 0xC6500080, 0xC7D01040, 0xC7901840, 0xCD000000, 0x58280002,
+ 0xCE400080, 0xC3C00200, 0x5FFC001C, 0xC3800000, 0xDF790050, 0x00000000, 0x00000000, 0x47BC8000,
+ 0x8800FFC2, 0xC0004862, 0xCBC00000, 0xC0000000, 0xC76C0000, 0x5BBC7200, 0xC280001C, 0xCA6C0001,
+ 0x00000000, 0x00000000, 0xCE780001, 0xC1007400, 0x47908000, 0xC1007200, 0xC5380006, 0x5EA80002,
+ 0x8400FFA0, 0xC3800000, 0xC000481A, 0xC8000000, 0x6F108000, 0x47108000, 0x47108000, 0x4011C000,
+ 0xC000491E, 0xCF800000, 0xC2C00000, 0xC7EC0068, 0xC100001C, 0xC52C1050, 0xC100000A, 0xC52C0D18,
+ 0xC000491C, 0xCEC00000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2800000, 0xDF680040,
+ 0x5D280080, 0x8800FFD0, 0xC000491C, 0xCAC00000, 0xC000491E, 0xCB800000, 0x99007F18, 0xDAD80000,
+ 0xDB980001, 0x00000000, 0xC00047CE, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x00000000, 0x80001868, 0x00000000, 0x00000000, 0x00000000, 0xC0004878, 0xC8040000, 0x6C908000,
+ 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000, 0x00000000, 0xC0004934, 0xCE000000,
+ 0xC2800002, 0xC4681C10, 0xC62821D8, 0xC6281E08, 0xC2600010, 0x5A650080, 0xC0004800, 0xCB400000,
+ 0xC2200400, 0x5A200040, 0xC7601048, 0xC0001220, 0xCE800000, 0xC0001200, 0xCE400000, 0xC0001202,
+ 0xCE000000, 0xC0001240, 0xCB400000, 0x00000000, 0x00000000, 0xA754FFC0, 0xC2000000, 0xC7600048,
+ 0xA7520022, 0x00000000, 0x00000000, 0x99008690, 0xC0004822, 0xC9400000, 0xC1800002, 0x800016F8,
+ 0x582040C0, 0xC2000000, 0xCA000020, 0xC2400000, 0xCA414008, 0xC2800000, 0xCA812008, 0xC2C00000,
+ 0xCAC20020, 0xC0004938, 0xCE000000, 0xC0004920, 0xCE400000, 0xC0004916, 0xCE800000, 0xC0004922,
+ 0xCEC00000, 0xA6400538, 0x00000000, 0xC0004938, 0xCBC00000, 0x00000000, 0xC3800000, 0x6FF48000,
+ 0x6FD44000, 0x4355A000, 0x5B744A00, 0x58340000, 0xCB802018, 0x00000000, 0xC2000000, 0x6FB46000,
+ 0x47B5A000, 0x5B744C80, 0x5834000C, 0xCA000028, 0xC000491A, 0xCF800000, 0x5E200000, 0x8400046A,
+ 0xC2000000, 0xDF610050, 0x5E6001E8, 0x8800FFD0, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000,
+ 0xC0001006, 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000, 0x99007958, 0xC1A0FFFE,
+ 0xC0000824, 0xC9840068, 0xC0004934, 0xCA400000, 0xC2000000, 0xC2800002, 0x99007998, 0xDA980000,
+ 0xC6140000, 0xC6580000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x99007A80, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0xC0004922, 0xCA001120, 0xC3C00000, 0xC3800000, 0xC0004930, 0xCE001120, 0xC0004932,
+ 0xCBC000E0, 0xC2800000, 0xC000491E, 0xCFC00000, 0xC0004862, 0xCA800068, 0xC3A0001A, 0x5BB94000,
+ 0xC6B80068, 0xC000491C, 0xCF800000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0x00000000,
+ 0x00000000, 0x00000000, 0xA8E2FFC8, 0xC2000000, 0xC1220002, 0xD90C0000, 0xDF600040, 0x5E600080,
+ 0x8400FFDA, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, 0x99007F18,
+ 0xDA180000, 0xDA580001, 0x00000000, 0xC2000000, 0xDF610050, 0x5E6001FE, 0x8800FFD0, 0xC0004916,
+ 0xCA800000, 0xC2C00000, 0xDFEC0050, 0xC2400000, 0x46E52000, 0x84000032, 0x5EA80000, 0x84000022,
+ 0xC2600002, 0x99008690, 0xC000482E, 0xC9400000, 0xC1800002, 0x80000018, 0xC2600000, 0x99008690,
+ 0xC000482C, 0xC9400000, 0xC1800002, 0xC2000068, 0xC6240080, 0xC0004930, 0xCE400088, 0xC000491A,
+ 0xC9800000, 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99007D78, 0xD9580000,
+ 0xD9980001, 0xD9D40000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xDF600040,
+ 0x5E600080, 0x8400FFD2, 0x00000000, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000,
+ 0x00000000, 0x99007F18, 0xDA180000, 0xDA580001, 0x00000000, 0x80001148, 0x00000000, 0x99008690,
+ 0xC000482A, 0xC9400000, 0xC1800002, 0x80001118, 0xC0004938, 0xCBC00000, 0x00000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0x58380008, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA600037A, 0x00000000, 0xC0004938, 0xCBC00000, 0xC3000000, 0x00000000, 0x6FF88000, 0x6FD44000,
+ 0x4395C000, 0x5BB84A00, 0x58380000, 0xCB002018, 0xC2000000, 0x58380008, 0xCA020080, 0x5838000C,
+ 0xCAC00000, 0x5838000E, 0xCA400000, 0xC000491A, 0xCF000000, 0xC0004930, 0xCEC00000, 0xC000493C,
+ 0xCE000000, 0xC0004932, 0xCE400000, 0x5E200000, 0x84000120, 0xC2800000, 0xA6FE00B2, 0x6F206000,
+ 0x47210000, 0x5A204C80, 0x5820000C, 0xCA800028, 0x00000000, 0x00000000, 0x5EA80000, 0x840001F2,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99007A80, 0xC000491A, 0xC9400000, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000,
+ 0xC0004930, 0xCAC00000, 0xC0004932, 0xCA400000, 0xC7EC1120, 0xC0004930, 0xCEC00000, 0x5838000C,
+ 0xCEC00000, 0x58000002, 0xCE400000, 0xC0004934, 0xCA000000, 0xC2400002, 0x6E642000, 0x6E642000,
+ 0x76252000, 0x84000012, 0xC2400002, 0x6E684000, 0x58380008, 0xCE800208, 0xA6000000, 0x6E682000,
+ 0x58380008, 0xCE800108, 0xC2400002, 0x6E642000, 0x76252000, 0x840000D2, 0x58380008, 0xCA000000,
+ 0xC2800000, 0xC2400000, 0xA60200A0, 0xDBA80000, 0x6F386000, 0x4739C000, 0x5BB84C80, 0x58380004,
+ 0xCA400080, 0x58380002, 0xCA800080, 0x00000000, 0xDEB80000, 0x46694000, 0x88000048, 0x00000000,
+ 0xC0004824, 0xCA000000, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE000000, 0x58380008, 0xCE400008,
+ 0x80000000, 0x00000000, 0x80000030, 0xC0004934, 0xCA000000, 0x00000000, 0x00000000, 0xA6020CAA,
+ 0x00000000, 0x00000000, 0x80000CE0, 0xC2800000, 0xC2000200, 0xC240001A, 0xDF690050, 0x46A14000,
+ 0x46694000, 0x8800FFBA, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA800000, 0xC0001006,
+ 0xCE000000, 0xC0001008, 0xCE400000, 0xC000100A, 0xCE800000, 0x99007958, 0xC1A0FFFE, 0xC0000824,
+ 0xC9840068, 0xC2000000, 0xC0004930, 0xCA02E010, 0x58380026, 0xCA400000, 0x00000000, 0xC2800000,
+ 0x99007998, 0xDA980000, 0xC6140000, 0xC6580000, 0xC0004934, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA6020002, 0x00000000, 0x00000000, 0x80000300, 0xC0004938, 0xCBC00000, 0xC0004878, 0xC8040000,
+ 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA000000, 0xC4240000, 0x00000000, 0x58240018,
+ 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB84A00, 0xC3000000, 0xC3400002, 0xC2C00000,
+ 0xC62C0080, 0xC6270040, 0xC0004940, 0xCE400040, 0xC6260040, 0xC0004942, 0xCE400040, 0xC000493C,
+ 0xCA000000, 0x5EEC0000, 0x84000172, 0x5A6C0010, 0x46614000, 0x88000178, 0x5A600052, 0x466D4000,
+ 0x88000160, 0x58380006, 0xCA800000, 0xC0004940, 0xCA000000, 0xC2400000, 0xC6A70040, 0x7E412000,
+ 0x76252000, 0xC2000000, 0xC6A10040, 0x46610000, 0x84000120, 0xC0004942, 0xCA000000, 0xC2400000,
+ 0xC6A60040, 0x7E412000, 0x76252000, 0xC2000000, 0xC6A00040, 0x58380002, 0xCA800000, 0x46610000,
+ 0x840000D0, 0xC2400000, 0xC6A60080, 0x46E50000, 0x880000C2, 0xC2400000, 0xC6A40080, 0x58380008,
+ 0xCA800000, 0x466D0000, 0x880000A2, 0x00000000, 0xA682FFF8, 0x00000000, 0xC7700B08, 0xA6840078,
+ 0x00000000, 0xC7700A08, 0x80000068, 0xC7700208, 0xC000493C, 0xCAC00000, 0x80000048, 0xC7700308,
+ 0xC000493C, 0xCAC00000, 0x80000028, 0xC7700908, 0x80000018, 0xC7700808, 0x80000008, 0xC7700708,
+ 0x8000FFF8, 0xC7700508, 0xC0004944, 0xCF000000, 0xC000493E, 0xCEC00000, 0xC0004938, 0xCA400000,
+ 0xC000493C, 0xCB800000, 0xC000493E, 0xCB400000, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000,
+ 0x5A204A00, 0x5AA00008, 0x58200004, 0xCB000080, 0xC0004934, 0xCA000000, 0xC2400000, 0xC0004930,
+ 0xCA42E010, 0xC3C00018, 0xA6020078, 0x00000000, 0x43656000, 0x46F90000, 0x88000038, 0x47AD6000,
+ 0x6EE04010, 0x5BE00004, 0xC2000000, 0xC6E00010, 0x5E200000, 0x8400002A, 0x5BFC0002, 0x80000018,
+ 0xC3C00004, 0x5A2C0008, 0x46390000, 0x8800FFFA, 0x5FB80008, 0x6FE04000, 0x42390000, 0x46312000,
+ 0x88000050, 0xC2400000, 0xC0004930, 0xCA42E010, 0xC2060002, 0xC6800000, 0xCE000308, 0x6FE04000,
+ 0x4631C000, 0x5F700010, 0x4675A000, 0xC2000000, 0xC6340010, 0xC25A000A, 0xC000491A, 0xCA401C20,
+ 0xC2800000, 0xC0004932, 0xCA8000E0, 0xC0004862, 0xCA400068, 0x6FA04010, 0x42290000, 0xC000491E,
+ 0xCE000000, 0xC7E41050, 0xC000491C, 0xCE400000, 0x6FE04000, 0x43A1C000, 0xC000493C, 0xCF800000,
+ 0xC000493E, 0xCF400000, 0xC000493A, 0xCFC00000, 0x8000FFF0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC2000000, 0xDCE00000, 0xA622FFB8, 0xC1220002, 0xD90C0000, 0xC0004938, 0xCBC00000, 0xC0004944,
+ 0xCB400000, 0xC0004862, 0xCB000000, 0xC0004934, 0xCA000000, 0x6FF88000, 0x6FD44000, 0x4395C000,
+ 0x5BB84A00, 0xA6020278, 0xC2400000, 0x58380008, 0xCA406008, 0xDFE80000, 0xC2218E08, 0x5A21BAF6,
+ 0x46294000, 0x8400000A, 0xC2080002, 0x7235A000, 0x80000040, 0x5E640000, 0x8400000A, 0xC20C0002,
+ 0x7235A000, 0x80000018, 0xC2000000, 0xC760E718, 0xC7604220, 0x5E200000, 0x8400028A, 0xC2200002,
+ 0xC0004930, 0xCE001008, 0x99008690, 0xC0004828, 0xC9400000, 0xC1800002, 0xC0004780, 0xC93C0000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C0000, 0x58380000, 0xCA000000, 0x00000000, 0x00000000,
+ 0xA6000112, 0xC0004940, 0xCA800000, 0xC0004942, 0xCA400000, 0xC7600080, 0xC6A01840, 0xC6601040,
+ 0xC000493A, 0xCA400000, 0xC0004934, 0xCA800000, 0xC0007200, 0x40300000, 0x40240000, 0x5C000004,
+ 0x5EC07400, 0x8800FFFA, 0x5C000200, 0xCE000000, 0x58000002, 0x5EC07400, 0x8800FFFA, 0x5C000200,
+ 0xCE800000, 0xC000493E, 0xCA000000, 0xC2400000, 0x5838000C, 0xCE400000, 0x99008690, 0xC0004830,
+ 0xC9400000, 0xC6180000, 0xC0004930, 0xC6100080, 0xCD000080, 0x80000090, 0xC2400002, 0x58380008,
+ 0xCE400008, 0xC0004944, 0xCF400000, 0x80000290, 0xC000493C, 0xCA400000, 0xDFE80000, 0x5A300018,
+ 0xC0007200, 0x40200000, 0xCA000000, 0x58380008, 0xC6501080, 0xCD001080, 0x5838000A, 0xCE800000,
+ 0x58380026, 0xCE000000, 0xC0004944, 0xCF400000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050,
+ 0x80000050, 0x00000000, 0x99008690, 0xC0004826, 0xC9400000, 0xC1800002, 0xC0004760, 0xC93C0000,
+ 0x00000000, 0x00000000, 0x59100002, 0xCD3C0000, 0x8000FD90, 0xC2000000, 0xC2400080, 0xDF600040,
+ 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99007F18, 0xDA580000, 0xDA980001,
+ 0x00000000, 0xC0004934, 0xCA000000, 0x00000000, 0xC2800000, 0xA6020140, 0xC2400004, 0xC2000200,
+ 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFC2, 0x00000000, 0xC000491A, 0xC9800000, 0xC0004862,
+ 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99007D78, 0xD9580000, 0xD9980001, 0xD9D40000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xC2400080, 0xDF600040, 0xB624FFCA,
+ 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99007F18, 0xDA580000, 0xDA980001, 0x00000000,
+ 0x58380008, 0xCA400000, 0xC2000000, 0xCE000020, 0xC2A1FFFE, 0x5AA9FFFE, 0xCE001080, 0x5838000A,
+ 0xCE800000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0000838, 0xC2500002, 0xCE440808, 0xC0004848, 0xCBC40000, 0xC3800000, 0xC000082C, 0xCB840030,
+ 0x5FFC0002, 0xC0004848, 0xCFC40000, 0x58880002, 0x44B88000, 0xC1000000, 0xC5080006, 0xC0004844,
+ 0xCC840000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000CBD8, 0xC2000000, 0xDF600040,
+ 0x5E200080, 0x84000282, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000480C, 0xCA000000, 0xC0004910, 0xCA400000, 0xC000492C, 0xCA800000,
+ 0xC0004968, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x76610000, 0x76A10000,
+ 0x762D6000, 0x840001C2, 0xC0004926, 0xCA400000, 0xC201FFFE, 0x762D6000, 0x5A640002, 0x6AE50010,
+ 0x5F200000, 0x84000002, 0x6A250000, 0x8000FFF8, 0xC6E00000, 0x62014008, 0xC0004926, 0xCE800000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004968,
+ 0xCA400000, 0xC2000002, 0x6A290000, 0x7E010000, 0x76252000, 0xCE400000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x6EB4A000, 0x6E944000, 0x4575A000, 0x46B5A000, 0x5B744E20, 0x58340002,
+ 0xC2000000, 0xCA0000E0, 0x5834002E, 0xC2400000, 0xCA400080, 0x6EB0A000, 0x6EBC4000, 0x47F18000,
+ 0x46B18000, 0x5B300E4E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024, 0xC7380068, 0xC6B81C20,
+ 0x99007F18, 0xDB980000, 0xDBD80001, 0x00000000, 0xC2000000, 0xDF600040, 0x5E200080, 0x840002BA,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA000000, 0xC000492A, 0xCA400000, 0xC000496A, 0xCB000000, 0xC0004956, 0xCAC00000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x76318000, 0x76718000, 0x84000202, 0xC201FFFE,
+ 0x76318000, 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x84000002, 0x6A2D0000, 0x8000FFF8, 0xC7200000,
+ 0x62016008, 0xC0004956, 0xCEC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000496A, 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000,
+ 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6EF4A000, 0x6ED44000, 0x4575A000,
+ 0x46F5A000, 0x5B744E20, 0x5834000E, 0xC2000000, 0xCA0000E0, 0x58340008, 0xC2400000, 0xCA420080,
+ 0x5834000C, 0xC2800000, 0xCA832018, 0x6E644010, 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008,
+ 0xCB809020, 0x58340008, 0xC2800000, 0xCA810018, 0x6EE0A000, 0x6EE44000, 0x46610000, 0x46E10000,
+ 0x5A200008, 0x5A200E28, 0x42290000, 0xC6380068, 0xC6F81C20, 0x99007F18, 0xDB980000, 0xDBD80001,
+ 0x00000000, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, 0xCC400000, 0xC0001A1C,
+ 0xCA000000, 0xC2400008, 0x6A452000, 0x76610000, 0x84000E82, 0xC0000A28, 0xC3800000, 0xCB840030,
+ 0xC0000A14, 0xC3400000, 0xCB440030, 0xC0004880, 0xCB040000, 0x47788000, 0x88000E30, 0x58041802,
+ 0xCAC00000, 0xA7000040, 0x00000000, 0x00000000, 0xA6C8C5A8, 0xC2800000, 0xC6E80020, 0x80000058,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000C578, 0x00000000, 0xC2800000, 0xC7282020, 0xC000490E,
+ 0xCA400000, 0x6BE9E000, 0x00000000, 0x77E52000, 0x8400C530, 0x6EA0A000, 0x6E944000, 0x45610000,
+ 0x46A10000, 0x5A204E20, 0x5820000C, 0xCA000000, 0xC0004946, 0xCE800000, 0xA6220378, 0x00000000,
+ 0xC2200060, 0xC0004948, 0xCE000010, 0xCE001040, 0xC240000A, 0xC000494A, 0xCE400000, 0xC2B60002,
+ 0xC0004964, 0xCE801B08, 0x990081E8, 0xC00048A0, 0xC8840000, 0x00000000, 0xC0004946, 0xCBC00000,
+ 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x99007FA8,
+ 0xDBD80000, 0xDB980001, 0x00000000, 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C,
+ 0x990081A0, 0xC9400001, 0xC9800000, 0x00000000, 0x99007F18, 0xD9580000, 0xD9980001, 0x00000000,
+ 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0,
+ 0xDBD80000, 0xDB980001, 0xC7D80000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6FF8A000,
+ 0x6FD44000, 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x58380010, 0xCA000000, 0xC0004874, 0xC8040000,
+ 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCA400000, 0xC4340000, 0x00000000, 0xC7400000,
+ 0xCE000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000, 0x00000000, 0xC121FFFE,
+ 0x5911FE54, 0x15000000, 0x99008690, 0xC0004836, 0xC9400000, 0xC1800002, 0x00000000, 0x00000000,
+ 0x00000000, 0xA8E2FFC8, 0x00000000, 0xC1220002, 0xD90C0000, 0xC2000000, 0xC0000A14, 0xCA040030,
+ 0xC0000A28, 0xC2500002, 0xCE440808, 0x58880002, 0xB608FFF8, 0xC00048A0, 0xC0800000, 0xCC840000,
+ 0x8000C150, 0xC0004946, 0xCBC00000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC000490E, 0xCA400000, 0xC2800002, 0x6ABD4000, 0x72A52000, 0xCE400000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x58380008, 0xCA000000, 0x5838000C, 0xCA400000, 0xC3400000, 0xC6340008, 0xC000494E,
+ 0xCF400000, 0xC2800000, 0xC62A0080, 0xC3000000, 0xC6308020, 0x6F304000, 0x43298000, 0xC000493C,
+ 0xCF000000, 0xC2C00000, 0xC66C0080, 0xC0004950, 0xCEC00000, 0xC2800000, 0xC66AE028, 0xC0004954,
+ 0xCE800000, 0x5F740000, 0x840001A0, 0x5E300028, 0x462D2000, 0x8400016A, 0x462D2000, 0x88000132,
+ 0x5E300018, 0x462D2000, 0x88000012, 0x462D2000, 0x8400002A, 0x00000000, 0x800000C0, 0x00000000,
+ 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC3400002, 0xC000494E, 0xCF400000, 0xC161FFFE,
+ 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC000490E, 0xCA400000,
+ 0xC2800002, 0x6ABD4000, 0x7E814000, 0x76A52000, 0xCE400000, 0x00000000, 0xC121FFFE, 0x5911FE54,
+ 0x15000000, 0xC2200060, 0xC0004948, 0xCE001040, 0xC2000000, 0xC000494C, 0xCE000000, 0x80000068,
+ 0x00000000, 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0x99008528, 0xDBD80000, 0xDB980001,
+ 0xC7800000, 0xC2200058, 0xC0004948, 0xCE001040, 0xC2000002, 0xC000494C, 0xCE000000, 0xC2000006,
+ 0xC0001006, 0xCE000000, 0x5838000A, 0xCA400000, 0xC2200982, 0x5A203B6E, 0xC0001008, 0xCE000000,
+ 0xC000100A, 0xCE400000, 0xC0004954, 0xCA800000, 0xC200000C, 0xC000494A, 0xCE000000, 0xC0004948,
+ 0xCE800010, 0xC2B60000, 0xC0004964, 0xCE800000, 0x990081E8, 0xC00048A0, 0xC8840000, 0x00000000,
+ 0xC0004946, 0xCBC00000, 0xC000494C, 0xCA000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000,
+ 0x5BB84E20, 0x5E200000, 0x840000FA, 0x00000000, 0x99007FA8, 0xDBD80000, 0xDB980001, 0x00000000,
+ 0x99007CF0, 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C, 0x990081A0, 0xC9400001, 0xC9800000,
+ 0x00000000, 0x99007F18, 0xD9580000, 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x99007BE0, 0xDBD80000, 0xDB980001, 0xC7D80000,
+ 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0xC000493C, 0xCA800000, 0xC000494E, 0xCAC00000,
+ 0xC3000018, 0xC3400006, 0x5E200000, 0x84000012, 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000,
+ 0xC6AC1080, 0xC72C0420, 0xC76C0818, 0x58380010, 0xCA800000, 0x58380008, 0xCEC00000, 0xC6280108,
+ 0xC0004874, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xCB000000, 0xC4340000,
+ 0x00000000, 0xC7400000, 0xCE800000, 0xC0004952, 0xCE800000, 0x00000000, 0x00000000, 0x00000000,
+ 0xA8E2FFC8, 0x00000000, 0xC000494C, 0xCA000000, 0xC0004950, 0xCAC00000, 0x5E200000, 0x84000052,
+ 0xDFE80000, 0x7E814000, 0x5834001A, 0xCE800000, 0x99008690, 0xC0004834, 0xC9400000, 0xC1800002,
+ 0x99008690, 0xC0004838, 0xC9400000, 0xC6D80000, 0xC1220002, 0xD90C0000, 0x5E200000, 0x84000028,
+ 0x5838002C, 0xCB000000, 0xDFE80000, 0x00000000, 0x58380014, 0xCF000000, 0x80000000, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0x5838000A, 0xCE800000, 0xC3000000, 0xC0000A14, 0xCB040030, 0xC2D00002, 0xC0000A28,
+ 0xCEC40808, 0xC000494E, 0xCA800000, 0x58880002, 0xB4B0FFF8, 0xC00048A0, 0xC0800000, 0xCC840000,
+ 0x5EA80000, 0x84000152, 0x5E200000, 0x84000140, 0xC000493C, 0xCA800000, 0x00000000, 0x00000000,
+ 0x5AA80060, 0xCE800000, 0x99008328, 0xDBD80000, 0xDB980001, 0xC7800000, 0x99008528, 0xDBD80000,
+ 0xDB980001, 0xC7800000, 0xC0004952, 0xCAC00000, 0x58380000, 0xCA800000, 0xC30C0002, 0xC7F00020,
+ 0xA6800090, 0x00000000, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xC0001800, 0xCA000000, 0x00000000, 0x00000000, 0xA60CFFCA, 0xC6F00508,
+ 0xC6B0C408, 0xCF000000, 0x00000000, 0xC121FFFE, 0x5911FE54, 0x15000000, 0x8000B7A0, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x8000B738, 0xDCBC0001, 0x5FFC0000, 0x84000942, 0xC3800002,
+ 0xDB880001, 0xC3800000, 0xDB880001, 0xC0004728, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xC0004730, 0xC9800000, 0xC000472E, 0xC9400000, 0xC00047DC, 0xC9000000, 0xC00047DE,
+ 0xC9C00000, 0xC000472E, 0xCD800000, 0x6D110000, 0xC5D30040, 0xC00047DC, 0xCD000000, 0x4558A000,
+ 0x6DDD0000, 0xC55C0040, 0xC00047DE, 0xCDC00000, 0xC0001AC4, 0xC9400000, 0xC0001AC8, 0xC9800000,
+ 0xC000472C, 0xC9C00000, 0x45588000, 0xC1000002, 0x41D0E004, 0xCDC00000, 0xC5501080, 0xC5900080,
+ 0xC000472A, 0xCD000000, 0xC0001AF0, 0xCBC00000, 0x58000002, 0xCB800000, 0xC3400000, 0xC7F50040,
+ 0x6F702000, 0x5B304300, 0xC000474C, 0xCAC00000, 0xC0004720, 0xC9400000, 0x00000000, 0x00000000,
+ 0x5D940002, 0x6D9B8000, 0x6D9B8010, 0x581847E0, 0xC9800000, 0x581447E0, 0xC9C00000, 0x5D2C0000,
+ 0x84000062, 0xC7901080, 0xC7D00080, 0xCD000000, 0xC1000000, 0xC5910040, 0x47508000, 0x84000078,
+ 0xC0004722, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x80000040, 0xC1000000,
+ 0xC5D10040, 0x47508000, 0x84000022, 0xC0004724, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xA7840060, 0x59540002, 0x6D578000, 0x6D578010, 0xC0004720, 0xCD400000, 0xC1000000,
+ 0xC5910040, 0x47508000, 0x84000020, 0xC0004726, 0xC9000000, 0x00000000, 0x00000000, 0x59100002,
+ 0xCD000000, 0xA7800098, 0xC2800002, 0xC000474E, 0xCE800000, 0xC2C00000, 0xC000474C, 0xCEC00000,
+ 0xC0004758, 0xCFC00000, 0x58000002, 0xCF800000, 0xC000475C, 0xC9000000, 0x00000000, 0x00000000,
+ 0xA53E001A, 0x00000000, 0xC13E0002, 0xCFC00000, 0xCD001E10, 0x58000002, 0xCF800000, 0x80000188,
+ 0xC000475C, 0xC13C0002, 0xCD001E10, 0x5D2C0000, 0x84000162, 0xC2C00000, 0xC000474C, 0xCEC00000,
+ 0x98C08AF0, 0xC7540000, 0xC0004740, 0xC9C00000, 0x5D240000, 0x8400002A, 0xC1000002, 0xC0004750,
+ 0xCD000000, 0xC0004752, 0xCD000000, 0x800000E8, 0x00000000, 0x98C08BE0, 0xC7540000, 0xC0004742,
+ 0xC9800000, 0x5D240000, 0x84000012, 0xC1000002, 0xC0004752, 0xCD000000, 0x80000048, 0xC0004742,
+ 0xC9400000, 0xC0004754, 0xC1000002, 0xCD000000, 0x98C08CF0, 0xC5540000, 0xC7580000, 0x00000000,
+ 0xC0004742, 0xCF400000, 0x98C08AB8, 0xC1400000, 0xC7540028, 0x6F40A010, 0xC1000000, 0xC7D00040,
+ 0x58300000, 0x6D110000, 0xCD000840, 0xA7840378, 0xC000474C, 0xCAC00000, 0xC000474E, 0xCA800000,
+ 0xC0004750, 0xCBC00000, 0xC0004752, 0xCB800000, 0xC0004710, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0x5D280002, 0x840000A0, 0xC000473C, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0xC0004712, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0xC0004754, 0xC9000000, 0x00000000, 0x00000000, 0x5D100000, 0x84000202, 0x58300000, 0xC13C0002,
+ 0xCD001E08, 0x800001E0, 0xC0004714, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x5D380000, 0x84000022, 0xC0004736, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x5D3C0000, 0x8400002A, 0xC0004718, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000,
+ 0x80000128, 0xC1000000, 0x58300000, 0xC903E008, 0x00000000, 0x00000000, 0x5D100000, 0x8400002A,
+ 0xC000471A, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x800000B8, 0x58300000,
+ 0xC13E0002, 0xCD001F08, 0xC1000000, 0x58300000, 0xC903C008, 0x00000000, 0x00000000, 0x5D100000,
+ 0x8400006A, 0xC0004716, 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0xC000473A,
+ 0xC9000000, 0x00000000, 0x00000000, 0x59100002, 0xCD000000, 0x58300000, 0xC13C0000, 0xCD001E08,
+ 0xC1000000, 0xC0004746, 0xCD000000, 0xC0004750, 0xCD000000, 0xC0004752, 0xCD000000, 0xC000474E,
+ 0xCD000000, 0xC2C00002, 0xC000474C, 0xCEC00000, 0xC0004754, 0xCD000000, 0xC3CE0002, 0xC0000800,
+ 0xCFC00708, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4380000, 0x00000000,
+ 0xC000480E, 0xCA000000, 0xC0004858, 0xCB440000, 0x00000000, 0x00000000, 0x46350000, 0x88000098,
+ 0x00000000, 0xA7C00028, 0xC0004854, 0xC1000002, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x800000C0, 0x00000000, 0xA7D20118, 0x00000000, 0xC7E14048, 0xC2400000, 0xC6246030, 0xC200006A,
+ 0x46610000, 0xC6240038, 0xC0000810, 0xCE440038, 0x8000FF58, 0xC2000000, 0xC0000808, 0xCA040018,
+ 0xC11C0000, 0xC000082C, 0xCD040E08, 0x5A200002, 0x5E600010, 0x8400FFF8, 0xC2000000, 0xC0000808,
+ 0xCE040018, 0xC3400000, 0x80000010, 0xC1200002, 0xC0000818, 0xCD041008, 0x5B740002, 0xC0004858,
+ 0xCF440000, 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD040E08,
+ 0x80000860, 0x5B740002, 0xC0004858, 0xCF440000, 0xC7800000, 0xC13C0002, 0xCD001E08, 0xC0004848,
+ 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002,
+ 0xB49807D8, 0x00000000, 0xC0800000, 0x800007C8, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000,
+ 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000, 0xA7C00110, 0xC000484C, 0xCA040000, 0xC2400000,
+ 0xC0001AEC, 0xCA440020, 0x5A200002, 0xC000484C, 0xCE040000, 0xB624006A, 0xC6800000, 0xC13C0002,
+ 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848,
+ 0xCD440000, 0x58880002, 0xB49806C8, 0x00000000, 0xC0800000, 0x800006B8, 0xC0004854, 0xC1000004,
+ 0xCD040000, 0xC0000820, 0xC2000002, 0xCE040000, 0xC2000000, 0xC000484C, 0xCE040000, 0xC0004858,
+ 0xCE040000, 0x8000FF10, 0xC0004854, 0xC1000000, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC1200000, 0xC0000818, 0xCD041008, 0xC11C0002,
+ 0xC000082C, 0xCD040E08, 0xC2000000, 0xC000484C, 0xCE040000, 0x800005B8, 0xC0001AC0, 0xCB840000,
+ 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000,
+ 0xA78004C2, 0x00000000, 0x00000000, 0xA7C00482, 0x00000000, 0xC0001B00, 0xC2060006, 0xCE040310,
+ 0xA7E8043A, 0x00000000, 0xC0004850, 0xCA040000, 0xC2400000, 0xC0004812, 0xCA420080, 0x5A200002,
+ 0xC0004850, 0xCE040000, 0x5E640000, 0x84000002, 0x46610000, 0x880002E0, 0xC6800000, 0xC13C0002,
+ 0xCD001E08, 0xC0001ACC, 0xC2000002, 0xCE040008, 0x5C440000, 0x84000238, 0xC0004810, 0xC9400000,
+ 0xC6800000, 0xCBC00000, 0x00000000, 0xC1000000, 0xA54001E8, 0xC53C1008, 0x00000000, 0xA7FC01D2,
+ 0xC0001AF0, 0xC1000000, 0x58000002, 0xC9000008, 0xC000474E, 0xC9800000, 0x5D100000, 0x8400000A,
+ 0xC1000002, 0xC53C1E08, 0x80000180, 0x5D180000, 0x8400000A, 0xC1000002, 0xC53C1E08, 0x80000158,
+ 0xC0004878, 0xC8040000, 0x6C908000, 0x44908000, 0x44908000, 0x40100000, 0xC9800000, 0xC4380000,
+ 0x00000000, 0xC000481E, 0xC9C00000, 0xC000481C, 0xCA000000, 0x00000000, 0x75D8C000, 0x46188000,
+ 0x840000D0, 0xC0001AF0, 0xC3400000, 0x58000000, 0xCB410040, 0xC0004746, 0xC9400000, 0x6F702000,
+ 0x5B304300, 0xC2C00000, 0x58300000, 0xCAC00040, 0x00000000, 0x00000000, 0x46D48000, 0x88000008,
+ 0xC1000002, 0xC53C1E08, 0x80000028, 0x5AEC0002, 0x58300000, 0xCEC00040, 0xC1000002, 0xC53C1008,
+ 0xC77C0840, 0xC57C0040, 0x59540002, 0xC0004746, 0xCD400000, 0xC6800000, 0xCFC00000, 0xC0004848,
+ 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, 0x59540002, 0xC0004848, 0xCD440000, 0x58880002,
+ 0xB49801D8, 0x00000000, 0xC0800000, 0x800001C8, 0xC000471E, 0xC9000000, 0x00000000, 0x00000000,
+ 0x59100002, 0xCD000000, 0xC0004854, 0xC1000000, 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08,
+ 0x99007930, 0xC0004848, 0xC9440000, 0xC1800000, 0xC2000000, 0xC0000820, 0xCE040000, 0xC1200000,
+ 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC0004850, 0xCE040000, 0xC2000002,
+ 0xC0001ACC, 0xCE040010, 0x800000D0, 0xC2000002, 0xC0004850, 0xCE040000, 0x8000FBE8, 0xC2000000,
+ 0xC0004850, 0xCE040000, 0xA7E60012, 0x00000000, 0xC2000002, 0xC0001B00, 0xCE040008, 0x8000FBD0,
+ 0x00000000, 0xA7860032, 0x00000000, 0xC6800000, 0xC13C0002, 0xCD001E08, 0xC2020002, 0xC7E2A548,
+ 0xC0001B00, 0xCE040000, 0x8000FB78, 0xC2040002, 0xC0001B00, 0xCE040208, 0x8000FB58, 0xC2C80002,
+ 0x6AC56000, 0xDACC0000, 0xC0004854, 0xCB440000, 0xC0004848, 0xCB840000, 0xC0000838, 0xC3C00000,
+ 0xCBC40030, 0x5EF40004, 0x8400000A, 0xC3000000, 0xC0001ACC, 0xCF040108, 0x47BD8000, 0x84000032,
+ 0x47BD8000, 0x88000038, 0xC1006E8C, 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0004840, 0xCC840000, 0x8000EAF8, 0xC0001AC0, 0xCAC40000, 0xC0004854, 0xCB440000, 0xA6C0F91A,
+ 0x00000000, 0x5EF40000, 0x8400F45A, 0x5EF40002, 0x8400F6EA, 0x5EF40004, 0x8400F8EA, 0xC1006CE8,
+ 0xC1400010, 0x8D580000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xC0800000, 0xDF4B0040,
+ 0xC0004900, 0xCB800000, 0xC2000000, 0xC000490A, 0xA78000B0, 0xCBC00000, 0xC1000000, 0xD9000001,
+ 0xC1000002, 0xD90C0000, 0x6FF46000, 0x47F5A000, 0x5B744C80, 0xC2400000, 0x58340004, 0xCA400080,
+ 0xC0004900, 0xCE000008, 0x5A640002, 0x58340004, 0xC6500080, 0xCD000080, 0xC0004914, 0xCA400000,
+ 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0xC0000408, 0xCE000000, 0xA78200B8, 0xC0004908,
+ 0xCBC00000, 0xC1000000, 0xD9000001, 0xC1000002, 0xD90C0000, 0x6FF4A000, 0x6FD44000, 0x4575A000,
+ 0x47F5A000, 0x5B744E20, 0xC2800000, 0x58340006, 0xCA800080, 0xC2000000, 0xC0004900, 0xCE000108,
+ 0x5EA80002, 0x58340006, 0xC6900080, 0xCD000080, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC0000408,
+ 0xCE000000, 0xC0000032, 0xDCA80001, 0xC1000002, 0x46914000, 0x00000000, 0x8C100006, 0x00000000,
+ 0x00000000, 0x00000000, 0xA4800210, 0x00000000, 0xC3C00000, 0xC000140E, 0xCBC00020, 0xC3400000,
+ 0xC2400000, 0x6FF86000, 0x47F9C000, 0x5BB84C80, 0x58380008, 0xCB400080, 0x58380006, 0xCA400080,
+ 0x5F740002, 0x58380008, 0xC7500080, 0xCD000080, 0xC2000000, 0x58380004, 0xCA020080, 0xC3000000,
+ 0x5838000C, 0xCB000028, 0x5A640002, 0x46250000, 0x8400FFF8, 0xC2400000, 0x58380006, 0xC6500080,
+ 0xCD000080, 0xC2000000, 0x5838000A, 0xCA020080, 0x5B300002, 0x5838000C, 0xC7100028, 0xCD000028,
+ 0xC2420020, 0x5A200004, 0x46612000, 0x8400FFF8, 0xC2000000, 0x5838000A, 0xC6101080, 0xCD001080,
+ 0xC0004966, 0xCA400000, 0xC2000002, 0x6A3D0000, 0x72252000, 0xCE400000, 0x5F740000, 0x84000028,
+ 0xC0004912, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x5F300020,
+ 0x84000028, 0xC0004924, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000,
+ 0xA4820050, 0xC2400000, 0xC000140E, 0xCA408020, 0xC2000002, 0xC0004900, 0xCE000008, 0xC000490A,
+ 0xCE400000, 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA4840288, 0x00000000,
+ 0xC3C00000, 0xC000140E, 0xCBC10020, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000, 0x4579C000,
+ 0x47F9C000, 0x5BB84E20, 0x5838002E, 0xCA800080, 0x58380006, 0xCA020080, 0xC3400000, 0x5838002E,
+ 0xCB420080, 0x5AA80002, 0x46290000, 0x8400FFF8, 0xC2800000, 0x5838002E, 0xC6900080, 0xCD000080,
+ 0x5F740002, 0x5838002E, 0xC7501080, 0xCD001080, 0xC0004968, 0xCA400000, 0xC2000002, 0x6A3D0000,
+ 0x72252000, 0xCE400000, 0xC000492A, 0xCA800000, 0x5E740000, 0x84000028, 0xC0004910, 0xCA000000,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x6ABD4010, 0xA68000D2, 0x00000000,
+ 0xC0004910, 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x76E10000, 0xCE000000, 0x58380032,
+ 0xCA000000, 0x58000002, 0xCA400000, 0x5838000C, 0x00000000, 0xCE000001, 0xCE400000, 0xC000492A,
+ 0xCA000000, 0xC2C00002, 0x6AFD6000, 0x72E10000, 0xCE000000, 0xC000492C, 0xCA000000, 0xC2C00002,
+ 0x6AFD6000, 0x72E10000, 0xCE000000, 0x80000028, 0xC000492C, 0xCA000000, 0xC2C00002, 0x6AFD6000,
+ 0x7EC16000, 0x76E10000, 0xCE000000, 0xA4880100, 0xC2C00000, 0xC000140E, 0xCAC20020, 0xC000490E,
+ 0xCA400000, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76252000, 0xCE400000, 0xC000496A, 0xCA400000,
+ 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0x6EF0A000, 0x6ED44000, 0x45718000, 0x46F18000,
+ 0x5B304E20, 0x58300000, 0xCA000000, 0x00000000, 0xC2400002, 0x76252000, 0x84000032, 0xC24C0002,
+ 0xC6E40020, 0xC624C408, 0x58300010, 0xCA400508, 0x00000000, 0xC0001800, 0xCE400000, 0xA4860050,
+ 0xC2400000, 0xC000140E, 0xCA418020, 0xC2020002, 0xC0004900, 0xCE000108, 0xC0004908, 0xCE400000,
+ 0xC1000000, 0xD9000001, 0xD8400080, 0xC1000004, 0xD9000001, 0xA48C0028, 0xC2800002, 0xC000484A,
+ 0xCE800000, 0xC2800000, 0xC000474A, 0xCE800000, 0xC0004846, 0xCE800000, 0xC0001408, 0xCC800000,
+ 0xC10E0002, 0xD90C0000, 0x8000EA60, 0xDFBC0001, 0xC000496E, 0x99008638, 0xC9400000, 0xC7D80000,
+ 0x00000000, 0xC5700000, 0x5EF00020, 0x88000130, 0x6F346000, 0x4735A000, 0x5B744C80, 0x58340008,
+ 0xC2400000, 0xCA400080, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400080, 0x58340004, 0xCA000080,
+ 0x00000000, 0x00000000, 0x5E200002, 0xCE000080, 0xC0004912, 0xCA800000, 0xC2400002, 0x6A712000,
+ 0x72694000, 0xCE800000, 0x5E200000, 0x8400003A, 0xC000480A, 0xCA000000, 0xC0000408, 0xCA800000,
+ 0x76610000, 0x00000000, 0x72294000, 0xCE800000, 0x80000020, 0xC0004914, 0xCA000000, 0x7E412000,
+ 0x00000000, 0x76610000, 0xCE000000, 0x800000B8, 0x6EF4A000, 0x6ED44000, 0x4575A000, 0x46F5A000,
+ 0x5B744E20, 0x5834002E, 0xC2400000, 0xCA420080, 0x00000000, 0xC2000000, 0x5A640002, 0xC6501080,
+ 0xCD001080, 0x58340006, 0xCA000080, 0x00000000, 0x00000000, 0x5A200002, 0xCE000080, 0xC0004910,
+ 0xCA400000, 0xC2000002, 0x6A2D0000, 0x72252000, 0xCE400000, 0xC2000002, 0x6A310000, 0xC000042A,
+ 0xCE000000, 0xC1040002, 0xD90C0000, 0x00000000, 0x8000E7D0, 0x00000000, 0xC4980930, 0x9D000000,
+ 0xC5580030, 0xC0000838, 0xCD840000, 0xC1440200, 0xC1C03200, 0xC55C1078, 0xC000100E, 0x9D000000,
+ 0xCD800000, 0xC000100C, 0xCDC00000, 0xC0004862, 0xC9C00000, 0x00000000, 0x00000000, 0xD9D80001,
+ 0xC0007200, 0x401C0000, 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0xC1F0000A, 0x71D4A000,
+ 0xDD980000, 0xDD9C0001, 0x41D8E000, 0xC5D40268, 0xC0001010, 0xCD400000, 0x6C9C8000, 0x449CE000,
+ 0x449CE000, 0x59DC0004, 0xC1601260, 0xC5D40268, 0x9D000000, 0xC0001012, 0xCD400000, 0x00000000,
+ 0x00000000, 0xD9580000, 0x6D586000, 0x4558C000, 0x59984C80, 0xD9980001, 0x5818000A, 0xC1800000,
+ 0xC9800080, 0xC0005400, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC9400000, 0x58000002, 0x00000000,
+ 0xC9C00000, 0xC0004930, 0xCD400000, 0xC0004932, 0xCDC00000, 0x59980004, 0xC1C20020, 0xB59CFFF8,
+ 0x00000000, 0xC1800000, 0xDD9C0001, 0x581C000A, 0xCD800080, 0x581C000C, 0xC1800000, 0xC9800028,
+ 0xC1C00002, 0xDD940000, 0x69D4E000, 0x5D980002, 0xCD800028, 0xC0004924, 0xC9800000, 0x00000000,
+ 0x9D000000, 0x00000000, 0x71D8C000, 0xCD800000, 0xC000492A, 0xC9400000, 0xC1C00002, 0x69D8E000,
+ 0x7DC0C000, 0x7594A000, 0xCD400000, 0xC000492C, 0xC9400000, 0xDD800001, 0x58000032, 0x75D4A000,
+ 0x84000078, 0xC9400001, 0xC9800000, 0xDD800001, 0x5800000C, 0x00000000, 0xCD400001, 0xCD800000,
+ 0xC000492C, 0xC9400000, 0xC000492A, 0xC9800000, 0x71D4A000, 0xC000492C, 0xCD400000, 0x71D8C000,
+ 0xC000492A, 0xCD800000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC0004862, 0xC9800000,
+ 0x00000000, 0xC1C00200, 0x4194C000, 0x45D8E000, 0x8800FFFA, 0xC5D80000, 0xC0004862, 0xCD800000,
+ 0xC0001406, 0xC9800000, 0xC1C00002, 0x9D000000, 0xC5D80A08, 0xC5581050, 0xCD800000, 0xC0004930,
+ 0xC9800000, 0xC0004932, 0xC9C00000, 0xC140000E, 0xC5581C20, 0xDD940000, 0xC0007200, 0x40140000,
+ 0x5D407400, 0x8800FFFA, 0x5C000200, 0xCD800000, 0x58000002, 0x5D407400, 0x8800FFFA, 0x5C000200,
+ 0xCDC00000, 0xDD540000, 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000, 0x58140000, 0xC98000E0,
+ 0x6DDC2000, 0xC000491E, 0x41D8E000, 0xCDC00000, 0xDD980000, 0xC1C00022, 0xC5D80D78, 0xDD940001,
+ 0xC5581C20, 0xC000491C, 0xCD800000, 0xDD540000, 0xC1C00000, 0x58140006, 0xC9C20080, 0xC1800000,
+ 0x58140004, 0xC9820080, 0x00000000, 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000, 0x9D000000,
+ 0x58140006, 0xC5D81080, 0xCD801080, 0xC0004860, 0xC9400000, 0xC1820080, 0xC1D00002, 0x58146B00,
+ 0xD5800000, 0x58000002, 0xD5800001, 0x59540004, 0xB558FFF8, 0xC0004860, 0xC1400000, 0xCD400000,
+ 0xDD980001, 0x9D000000, 0xDD940000, 0xC0001404, 0xCDC00808, 0xC1C00000, 0xC1800200, 0x5D980004,
+ 0xDF5D0050, 0x45D8A000, 0x8800FFDA, 0xDD800001, 0x5800000C, 0x00000000, 0xC9400001, 0xC9800000,
+ 0xC1C00002, 0xC5D43F08, 0xC5D81E08, 0xC0004862, 0xC9C00000, 0x00000000, 0x00000000, 0x581C7200,
+ 0x5DC07400, 0x8800FFFA, 0x5C000200, 0xCD400000, 0x58000002, 0x5DC07400, 0x8800FFFA, 0x5C000200,
+ 0xCD800000, 0xC0004862, 0xC9C00000, 0x00000000, 0xC15004C0, 0xC5D40068, 0xDD9C0000, 0xC5D41C20,
+ 0xC1C00000, 0xDD800001, 0x58000030, 0xC9C00080, 0xDD800001, 0x58000002, 0xC9800000, 0x6DDC2000,
+ 0xC000491C, 0x41D8E000, 0xCD400001, 0xCDC00000, 0xDD940001, 0xC1C00000, 0x58140030, 0xC9C00080,
+ 0xC1800000, 0x58140006, 0xC9820080, 0x00000000, 0x59DC0002, 0x459CC000, 0x8400FFF8, 0xC1C00000,
+ 0x9D000000, 0x58140030, 0xC5D80080, 0xCD800080, 0xC1C00000, 0xDF5C0040, 0x5DDC0080, 0x8400FFD2,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC0000A10, 0xC9440068,
+ 0xC1A0FFFE, 0x59980E28, 0xC000100C, 0xCD400000, 0xC000100E, 0xCD800000, 0xC0004964, 0xC9800000,
+ 0x00000000, 0xC170000A, 0x7194A000, 0x6C988000, 0x4498C000, 0x4498C000, 0x59980004, 0xC5940278,
+ 0xC0001010, 0xCD400000, 0xC0004946, 0xC9400000, 0x00000000, 0x00000000, 0x6D58A000, 0x6D5C4000,
+ 0x45D8C000, 0x4558C000, 0xC000494A, 0xC9400000, 0xC0004948, 0xC9C00000, 0x4194C000, 0xC1400012,
+ 0xC55C1820, 0x9D000000, 0xC59C0270, 0xC0001012, 0xCDC00000, 0xC1400000, 0x58000012, 0xC9410040,
+ 0xC0004950, 0xC9C00000, 0xC5580000, 0xC5940840, 0xC5581080, 0xD9940000, 0xC000493C, 0xC9400000,
+ 0xC0004954, 0xC9800000, 0x59DC00A8, 0x455CE000, 0x41D8E000, 0x5D5C0030, 0x8800FFF8, 0xC1C00030,
+ 0xC1800000, 0xC5D84030, 0xC1400000, 0xC5D40010, 0x5DD40002, 0x8400005A, 0x5DD40004, 0x84000082,
+ 0x5DD40006, 0x840000AA, 0x5DD80026, 0x840000D2, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000,
+ 0xCD400000, 0x59980002, 0x8000FFA8, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD4000C0,
+ 0x59980002, 0x8000FF70, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400080, 0x59980002,
+ 0x8000FF38, 0xDD540000, 0xDD800001, 0x58000008, 0x40180000, 0xCD400040, 0x59980002, 0x8000FF00,
+ 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC9400000, 0xC0004954,
+ 0xC9C00000, 0xC0004950, 0xC9400080, 0xDD800001, 0x58000028, 0x5D9C0000, 0x8400003A, 0x5D9C0002,
+ 0x8400003A, 0x5D9C0004, 0x84000052, 0xC55B0040, 0xC55C08C0, 0xCD800041, 0xCDC008C0, 0x80000048,
+ 0xCD400000, 0x80000038, 0xC55900C0, 0xC55C1840, 0xCD8000C1, 0xCDC01840, 0x80000010, 0xC55A0080,
+ 0xC55C1080, 0xCD800081, 0xCDC01080, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x59540002,
+ 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x8800FFFA, 0xC5940000, 0x9D000000, 0xCD400000,
+ 0x00000000, 0x00000000, 0x9D000000, 0x4158A000, 0xCD400000, 0x00000000, 0xCD800001, 0x44148000,
+ 0x8800FFD8, 0x00000000, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004810, 0xCA010040,
+ 0xC241FFFE, 0xC1400000, 0x45608000, 0x00000000, 0x9CC00006, 0xC0004200, 0x40180000, 0xC9C00000,
+ 0x00000000, 0x00000000, 0x61C08010, 0x84000042, 0xC2400002, 0x6A512000, 0x725CE000, 0xCDC00000,
+ 0xC0004748, 0xCD800000, 0x9CC00000, 0x6D98A000, 0x5998003E, 0x45192000, 0x59540002, 0x59980002,
+ 0x45A08000, 0xC1000000, 0xC5180006, 0x8000FF20, 0x00000000, 0x40180000, 0xC9C00000, 0xC2000000,
+ 0xC5600028, 0xC1210000, 0x69208010, 0x7D008000, 0x751CE000, 0xCDC00000, 0x6D542000, 0x58144300,
+ 0xC1000000, 0xCD000001, 0x9CC00000, 0xC121FFFE, 0x5911FFFE, 0xCD000001, 0x79948000, 0x6D10A010,
+ 0x5D100000, 0x840000A8, 0x45588000, 0x88000098, 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700,
+ 0x40140000, 0xCA000000, 0x00000000, 0x00000000, 0x6A110000, 0x6A110010, 0x62008018, 0x8400001A,
+ 0x00000000, 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45152000, 0x59540002, 0x6D57A000, 0x6D57A010,
+ 0x6D54A000, 0x6D936000, 0x6D136010, 0xC1E10000, 0x69D0E010, 0x5DDC0002, 0x7DC0E000, 0x6D98A010,
+ 0x6D536000, 0x6D136010, 0x6D54A010, 0xC0004700, 0x40140000, 0xCA000000, 0x00000000, 0x00000000,
+ 0x6A110000, 0x6A110010, 0x45948000, 0x00000000, 0x75E10002, 0x62008018, 0x8400001A, 0x00000000,
+ 0x9CC00000, 0x6D54A000, 0x5954003E, 0x45152000, 0x45948000, 0x00000000, 0x9CC00002, 0x59540002,
+ 0x6D57A000, 0x6D57A010, 0xC0004700, 0x40140000, 0xCA000000, 0x8000FF50, 0x00000000, 0x00000000,
+ 0x00000000, 0x58004700, 0xC9800000, 0x9CC00000, 0x00000000, 0x6994C000, 0x6DA7E010, 0x58004700,
+ 0xC9800000, 0xC1210000, 0x9CC00000, 0x69148010, 0x7118C000, 0xCD800000, 0xC1000000, 0xC0004810,
+ 0xC9020040, 0x00000000, 0x00000000, 0x451CC000, 0x8800004A, 0xC2400002, 0x45948000, 0xC1000000,
+ 0xC5240004, 0x455C8000, 0xC1000000, 0xC5240006, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59980200, 0xC2400000, 0x45D48000, 0xC1000002, 0xC5240004, 0x45588000, 0xC1000002, 0xC5240006,
+ 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0xC0004740, 0xC9C00000, 0x59180002, 0x6D130000,
+ 0x6D130010, 0x45D08000, 0xC2400000, 0x9CC00002, 0x00000000, 0x00000000, 0x45D88000, 0x8800004A,
+ 0xC2400002, 0x45D48000, 0xC1000000, 0xC5240004, 0x45588000, 0xC1000000, 0xC5240004, 0x9CC00000,
+ 0x00000000, 0x00000000, 0x00000000, 0xC2400000, 0x45948000, 0xC1000002, 0xC5240006, 0x455C8000,
+ 0xC1000002, 0xC5240006, 0x9CC00000, 0x00000000, 0x00000000, 0x00000000, 0x59540002, 0x6D570000,
+ 0x6D570010, 0x45948000, 0x6D402000, 0x9CC00002, 0x58004300, 0x58000000, 0xC13C0002, 0xCD001E08,
+ 0x8000FF98, 0x00000000, 0x00000000, 0x00000000, 0xC1020002, 0xD90C0000, 0xC9800000, 0x59540002,
+ 0xC0004730, 0xCD400000, 0x5D980002, 0x00000000, 0x8000001E, 0x00000000, 0x9CC00000, 0xC0004732,
+ 0xCD800000, 0x00000000, 0xC0004734, 0xC9C00000, 0xC1800000, 0xC0004816, 0xC9820080, 0xC0004738,
+ 0xCDC00000, 0xC1C00000, 0xC0004734, 0x9CC00000, 0xCDC00000, 0xC0004732, 0xCD800000,
+};
+
+static unsigned int firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_DANUBE_H
diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h new file mode 100644 index 0000000000..af2b550869 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_amazon_se.h @@ -0,0 +1,30 @@ +#ifndef IFXMIPS_ATM_FW_REGS_AMAZON_SE_H +#define IFXMIPS_ATM_FW_REGS_AMAZON_SE_H + + + +/* + * Host-PPE Communication Data Address Mapping + */ +#define FW_VER_ID SB_BUFFER(0x2001) /* Firmware Version ID */ +#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */ +#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */ +#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */ +#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */ +#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */ +#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */ +#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20)) +#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7)) +#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i))) +#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x2F00 + (i) * 27)) +#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x2F01 + (i) * 27)) +#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410)) +#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x3200 + (i))) +#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x3220 + (i))) +#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x3240 + (i))) + + + +#endif // IFXMIPS_ATM_FW_REGS_AMAZON_SE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h new file mode 100644 index 0000000000..dd010f54f9 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_ar9.h @@ -0,0 +1,172 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_regs_ar9.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (Firmware Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_FW_REGS_AR9_H +#define IFXMIPS_ATM_FW_REGS_AR9_H + + + +/* + * Host-PPE Communication Data Address Mapping + */ +#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001)) +#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */ +#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */ +#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */ +#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */ +#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */ +#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */ +#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20)) +#define WRX_QUEUE_CONTEXT(i) ((struct wrx_queue_context*) SB_BUFFER(0x2504 + (i) * 20)) +#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7)) +#define WRX_DESC_CONTEXT(i) ((struct wrx_desc_context*) SB_BUFFER(0x2643 + (i) * 7)) +#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i))) +#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x3800 + (i) * 27)) +#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x3801 + (i) * 27)) +#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410)) +#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2010 + (i))) +#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2030 + (i))) +#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2050 + (i))) + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + + #define RETX_MODE_CFG ((volatile struct Retx_mode_cfg *) SB_BUFFER(0x2408)) + #define RETX_TSYNC_CFG ((volatile struct Retx_Tsync_cfg *) SB_BUFFER(0x2409)) + #define RETX_TD_CFG ((volatile struct Retx_Td_cfg *) SB_BUFFER(0x240A)) + #define RETX_MIB_TIMER_CFG ((volatile struct Retx_MIB_Timer_cfg *) SB_BUFFER(0x240B)) + #define RETX_PLAYOUT_BUFFER_BASE SB_BUFFER(0x240D) + #define RETX_SERVICE_HEADER_CFG SB_BUFFER(0x240E) + #define RETX_MASK_HEADER_CFG SB_BUFFER(0x240F) + + #define RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) PPE_REG_ADDR(0x0D78)) + #define BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AC)) + #define FIRST_BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AE)) + + #define PB_BUFFER_USAGE SB_BUFFER(0x2100) + #define DTU_STAT_INFO ((volatile struct DTU_stat_info *) SB_BUFFER(0x2180)) + #define DTU_VLD_STAT SB_BUFFER(0x2380) + + + //===================================================================== + // retx firmware mib, for debug purpose + // address : 0x2388 - 0x238F + // size : 8 + //===================================================================== + #define URETX_RX_TOTAL_DTU SB_BUFFER(0x2388) + #define URETX_RX_BAD_DTU SB_BUFFER(0x2389) + #define URETX_RX_GOOD_DTU SB_BUFFER(0x238A) + #define URETX_RX_CORRECTED_DTU SB_BUFFER(0x238B) + #define URETX_RX_OUTOFDATE_DTU SB_BUFFER(0x238C) + #define URETX_RX_DUPLICATE_DTU SB_BUFFER(0x238D) + #define URETX_RX_TIMEOUT_DTU SB_BUFFER(0x238E) + + #define URETX_ALPHA_SWITCH_TO_HUNT_TIMES SB_BUFFER(0x238F) + + // cell counter for debug purpose + #define WRX_BC0_CELL_NUM SB_BUFFER(0x23E0) + #define WRX_BC0_DROP_CELL_NUM SB_BUFFER(0x23E1) + #define WRX_BC0_NONRETX_CELL_NUM SB_BUFFER(0x23E2) + #define WRX_BC0_RETX_CELL_NUM SB_BUFFER(0x23E3) + #define WRX_BC0_OUTOFDATE_CELL_NUM SB_BUFFER(0x23E4) + #define WRX_BC0_DIRECTUP_NUM SB_BUFFER(0x23E5) + #define WRX_BC0_PBW_TOTAL_NUM SB_BUFFER(0x23E6) + #define WRX_BC0_PBW_SUCC_NUM SB_BUFFER(0x23E7) + #define WRX_BC0_PBW_FAIL_NUM SB_BUFFER(0x23E8) + #define WRX_BC1_CELL_NUM SB_BUFFER(0x23E9) + + // debug info (interface) + + #define DBG_DTU_INTF_WRPTR SB_BUFFER(0x2390) + #define DBG_INTF_FCW_DUP_CNT SB_BUFFER(0x2391) + #define DBG_INTF_SID_CHANGE_IN_DTU_CNT SB_BUFFER(0x2392) + #define DBG_INTF_LCW_DUP_CNT SB_BUFFER(0x2393) + + #define DBG_RFBI_DONE_INT_CNT SB_BUFFER(0x2394) + #define DBG_DREG_BEG_END SB_BUFFER(0x2395) + #define DBG_RFBI_BC0_INVALID_CNT SB_BUFFER(0x2396) + #define DBG_RFBI_LAST_T SB_BUFFER(0x2397) + + #define DBG_RFBI_INTV0 SB_BUFFER(0x23EE) + #define DBG_RFBI_INTV1 SB_BUFFER(0x23EF) + + #define DBG_INTF_INFO(i) ((volatile struct Retx_adsl_ppe_intf_rec *) SB_BUFFER(0x23F0 + i)) + + // Internal status + #define URetx_curr_time SB_BUFFER(0x2398) + #define URetx_sec_counter SB_BUFFER(0x2399) + #define RxCURR_EFB SB_BUFFER(0x239A) + #define RxDTURetransmittedCNT SB_BUFFER(0x239B) + + //===================================================================== + // standardized MIB counter + // address : 0x239C - 0x239F + // size : 4 + //===================================================================== + #define RxLastEFBCNT SB_BUFFER(0x239C) + #define RxDTUCorrectedCNT SB_BUFFER(0x239D) + #define RxDTUCorruptedCNT SB_BUFFER(0x239E) + #define RxRetxDTUUncorrectedCNT SB_BUFFER(0x239F) + + + //===================================================================== + // General URetx Context + // address : 0x23A0 - 0x23AF + // size : 16 + //===================================================================== + #define NEXT_DTU_SID_OUT SB_BUFFER(0x23A0) + #define LAST_DTU_SID_IN SB_BUFFER(0x23A1) + #define NEXT_CELL_SID_OUT SB_BUFFER(0x23A2) + #define ISR_CELL_ID SB_BUFFER(0x23A3) + #define PB_CELL_SEARCH_IDX SB_BUFFER(0x23A4) + #define PB_READ_PEND_FLAG SB_BUFFER(0x23A5) + #define RFBI_FIRST_CW SB_BUFFER(0x23A6) + #define RFBI_BAD_CW SB_BUFFER(0x23A7) + #define RFBI_INVALID_CW SB_BUFFER(0x23A8) + #define RFBI_RETX_CW SB_BUFFER(0x23A9) + #define RFBI_CHK_DTU_STATUS SB_BUFFER(0x23AA) + + //===================================================================== + // per PVC counter for RX error_pdu and correct_pdu + // address : 0x23B0 - 0x23CF + // size : 32 + //===================================================================== + #define WRX_PER_PVC_CORRECT_PDU_BASE SB_BUFFER(0x23B0) + #define WRX_PER_PVC_ERROR_PDU_BASE SB_BUFFER(0x23C0) + + #define __WRXCTXT_L2_RdPtr(i) SB_BUFFER(0x2422 + (i)) + #define __WRXCTXT_L2Pages(i) SB_BUFFER(0x2424 + (i)) + + #define __WTXCTXT_TC_WRPTR(i) SB_BUFFER(0x2450 + (i)) + #define __WRXCTXT_PortState(i) SB_BUFFER(0x242A + (i)) + +#endif + + + +#endif // IFXMIPS_ATM_FW_REGS_AR9_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_common.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_common.h new file mode 100644 index 0000000000..432969b933 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_common.h @@ -0,0 +1,546 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_regs_common.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (Firmware Register Structures) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_FW_REGS_COMMON_H +#define IFXMIPS_ATM_FW_REGS_COMMON_H + + + +#if defined(CONFIG_DANUBE) + #include "ifxmips_atm_fw_regs_danube.h" +#elif defined(CONFIG_AMAZON_SE) + #include "ifxmips_atm_fw_regs_amazon_se.h" +#elif defined(CONFIG_AR9) + #include "ifxmips_atm_fw_regs_ar9.h" +#elif defined(CONFIG_VR9) + #include "ifxmips_atm_fw_regs_vr9.h" +#else + #error Platform is not specified! +#endif + + + +/* + * PPE ATM Cell Header + */ +#if defined(__BIG_ENDIAN) + struct uni_cell_header { + unsigned int gfc :4; + unsigned int vpi :8; + unsigned int vci :16; + unsigned int pti :3; + unsigned int clp :1; + }; +#else + struct uni_cell_header { + unsigned int clp :1; + unsigned int pti :3; + unsigned int vci :16; + unsigned int vpi :8; + unsigned int gfc :4; + }; +#endif // defined(__BIG_ENDIAN) + +/* + * Inband Header and Trailer + */ +#if defined(__BIG_ENDIAN) + struct rx_inband_trailer { + /* 0 - 3h */ + unsigned int uu :8; + unsigned int cpi :8; + unsigned int stw_res1:4; + unsigned int stw_clp :1; + unsigned int stw_ec :1; + unsigned int stw_uu :1; + unsigned int stw_cpi :1; + unsigned int stw_ovz :1; + unsigned int stw_mfl :1; + unsigned int stw_usz :1; + unsigned int stw_crc :1; + unsigned int stw_il :1; + unsigned int stw_ra :1; + unsigned int stw_res2:2; + /* 4 - 7h */ + unsigned int gfc :4; + unsigned int vpi :8; + unsigned int vci :16; + unsigned int pti :3; + unsigned int clp :1; + }; + + struct tx_inband_header { + /* 0 - 3h */ + unsigned int gfc :4; + unsigned int vpi :8; + unsigned int vci :16; + unsigned int pti :3; + unsigned int clp :1; + /* 4 - 7h */ + unsigned int uu :8; + unsigned int cpi :8; + unsigned int pad :8; + unsigned int res1 :8; + }; +#else + struct rx_inband_trailer { + /* 0 - 3h */ + unsigned int stw_res2:2; + unsigned int stw_ra :1; + unsigned int stw_il :1; + unsigned int stw_crc :1; + unsigned int stw_usz :1; + unsigned int stw_mfl :1; + unsigned int stw_ovz :1; + unsigned int stw_cpi :1; + unsigned int stw_uu :1; + unsigned int stw_ec :1; + unsigned int stw_clp :1; + unsigned int stw_res1:4; + unsigned int cpi :8; + unsigned int uu :8; + /* 4 - 7h */ + unsigned int clp :1; + unsigned int pti :3; + unsigned int vci :16; + unsigned int vpi :8; + unsigned int gfc :4; + }; + + struct tx_inband_header { + /* 0 - 3h */ + unsigned int clp :1; + unsigned int pti :3; + unsigned int vci :16; + unsigned int vpi :8; + unsigned int gfc :4; + /* 4 - 7h */ + unsigned int res1 :8; + unsigned int pad :8; + unsigned int cpi :8; + unsigned int uu :8; + }; +#endif // defined(__BIG_ENDIAN) + +/* + * MIB Table Maintained by Firmware + */ +struct wan_mib_table { + u32 res1; + u32 wrx_drophtu_cell; + u32 wrx_dropdes_pdu; + u32 wrx_correct_pdu; + u32 wrx_err_pdu; + u32 wrx_dropdes_cell; + u32 wrx_correct_cell; + u32 wrx_err_cell; + u32 wrx_total_byte; + u32 res2; + u32 wtx_total_pdu; + u32 wtx_total_cell; + u32 wtx_total_byte; +}; + +/* + * Host-PPE Communication Data Structure + */ + +#if defined(__BIG_ENDIAN) + struct fw_ver_id { + unsigned int family :4; + unsigned int fwtype :4; + unsigned int interface :4; + unsigned int fwmode :4; + unsigned int major :8; + unsigned int minor :8; + }; + + struct wrx_queue_config { + /* 0h */ + unsigned int res2 :27; + unsigned int dmach :4; + unsigned int errdp :1; + /* 1h */ + unsigned int oversize :16; + unsigned int undersize :16; + /* 2h */ + unsigned int res1 :16; + unsigned int mfs :16; + /* 3h */ + unsigned int uumask :8; + unsigned int cpimask :8; + unsigned int uuexp :8; + unsigned int cpiexp :8; + }; + + struct wrx_queue_context { + /* 0h */ + unsigned int curr_len :16; + unsigned int res0 :12; + unsigned int mfs :1; + unsigned int ec :1; + unsigned int clp1 :1; + unsigned int aal5dp :1; + + /* 1h */ + unsigned int intcrc; + + /* 2h, 3h */ + unsigned int curr_des0; + unsigned int curr_des1; + + /* 4h - 0xE */ + unsigned int res1[11]; + + unsigned int last_dword; + }; + + struct wtx_port_config { + unsigned int res1 :27; + unsigned int qid :4; + unsigned int qsben :1; + }; + + struct wtx_queue_config { + unsigned int res1 :25; + unsigned int sbid :1; + unsigned int qsb_vcid :4; // Which QSB queue (VCID) does this TX queue map to. + unsigned int res2 :1; + unsigned int qsben :1; + }; + + struct wrx_desc_context { + unsigned int dmach_wrptr : 16; + unsigned int dmach_rdptr : 16; + + unsigned int res0 : 16; + unsigned int dmach_fcnt : 16; + + unsigned int res1 : 11; + unsigned int desbuf_wrptr : 5; + unsigned int res2 : 11; + unsigned int desbuf_rdptr : 5; + + unsigned int res3 : 27; + unsigned int desbuf_vcnt : 5; + }; + + struct wrx_dma_channel_config { + /* 0h */ + unsigned int res1 :1; + unsigned int mode :2; + unsigned int rlcfg :1; + unsigned int desba :28; + /* 1h */ + unsigned int chrl :16; + unsigned int clp1th :16; + /* 2h */ + unsigned int deslen :16; + unsigned int vlddes :16; + }; + + struct wtx_dma_channel_config { + /* 0h */ + unsigned int res2 :1; + unsigned int mode :2; + unsigned int res3 :1; + unsigned int desba :28; + /* 1h */ + unsigned int res1 :32; + /* 2h */ + unsigned int deslen :16; + unsigned int vlddes :16; + }; + + struct htu_entry { + unsigned int res1 :1; + unsigned int clp :1; + unsigned int pid :2; + unsigned int vpi :8; + unsigned int vci :16; + unsigned int pti :3; + unsigned int vld :1; + }; + + struct htu_mask { + unsigned int set :1; + unsigned int clp :1; + unsigned int pid_mask :2; + unsigned int vpi_mask :8; + unsigned int vci_mask :16; + unsigned int pti_mask :3; + unsigned int clear :1; + }; + + struct htu_result { + unsigned int res1 :12; + unsigned int cellid :4; + unsigned int res2 :5; + unsigned int type :1; + unsigned int ven :1; + unsigned int res3 :5; + unsigned int qid :4; + }; + + struct rx_descriptor { + /* 0 - 3h */ + unsigned int own :1; + unsigned int c :1; + unsigned int sop :1; + unsigned int eop :1; + unsigned int res1 :3; + unsigned int byteoff :2; + unsigned int res2 :2; + unsigned int id :4; + unsigned int err :1; + unsigned int datalen :16; + /* 4 - 7h */ + unsigned int res3 :4; + unsigned int dataptr :28; + }; + + struct tx_descriptor { + /* 0 - 3h */ + unsigned int own :1; + unsigned int c :1; + unsigned int sop :1; + unsigned int eop :1; + unsigned int byteoff :5; + unsigned int res1 :5; + unsigned int iscell :1; + unsigned int clp :1; + unsigned int datalen :16; + /* 4 - 7h */ + unsigned int res2 :4; + unsigned int dataptr :28; + }; +#else + struct wrx_queue_config { + /* 0h */ + unsigned int errdp :1; + unsigned int dmach :4; + unsigned int res2 :27; + /* 1h */ + unsigned int undersize :16; + unsigned int oversize :16; + /* 2h */ + unsigned int mfs :16; + unsigned int res1 :16; + /* 3h */ + unsigned int cpiexp :8; + unsigned int uuexp :8; + unsigned int cpimask :8; + unsigned int uumask :8; + }; + + struct wtx_port_config { + unsigned int qsben :1; + unsigned int qid :4; + unsigned int res1 :27; + }; + + struct wtx_queue_config { + unsigned int qsben :1; + unsigned int res2 :1; + unsigned int qsb_vcid :4; // Which QSB queue (VCID) does this TX queue map to. + unsigned int sbid :1; + unsigned int res1 :25; + }; + + struct wrx_dma_channel_config + { + /* 0h */ + unsigned int desba :28; + unsigned int rlcfg :1; + unsigned int mode :2; + unsigned int res1 :1; + /* 1h */ + unsigned int clp1th :16; + unsigned int chrl :16; + /* 2h */ + unsigned int vlddes :16; + unsigned int deslen :16; + }; + + struct wtx_dma_channel_config { + /* 0h */ + unsigned int desba :28; + unsigned int res3 :1; + unsigned int mode :2; + unsigned int res2 :1; + /* 1h */ + unsigned int res1 :32; + /* 2h */ + unsigned int vlddes :16; + unsigned int deslen :16; + }; + + struct rx_descriptor { + /* 4 - 7h */ + unsigned int dataptr :28; + unsigned int res3 :4; + /* 0 - 3h */ + unsigned int datalen :16; + unsigned int err :1; + unsigned int id :4; + unsigned int res2 :2; + unsigned int byteoff :2; + unsigned int res1 :3; + unsigned int eop :1; + unsigned int sop :1; + unsigned int c :1; + unsigned int own :1; + }; + + struct tx_descriptor { + /* 4 - 7h */ + unsigned int dataptr :28; + unsigned int res2 :4; + /* 0 - 3h */ + unsigned int datalen :16; + unsigned int clp :1; + unsigned int iscell :1; + unsigned int res1 :5; + unsigned int byteoff :5; + unsigned int eop :1; + unsigned int sop :1; + unsigned int c :1; + unsigned int own :1; + }; +#endif // defined(__BIG_ENDIAN) + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + #if defined(__BIG_ENDIAN) + + struct Retx_adsl_ppe_intf { + unsigned int res0_0 : 16; + unsigned int dtu_sid : 8; + unsigned int dtu_timestamp : 8; + + unsigned int res1_0 : 16; + unsigned int local_time : 8; + unsigned int res1_1 : 5; + unsigned int is_last_cw : 1; + unsigned int reinit_flag : 1; + unsigned int is_bad_cw : 1; + }; + + struct Retx_adsl_ppe_intf_rec { + + unsigned int local_time : 8; + unsigned int res1_1 : 5; + unsigned int is_last_cw : 1; + unsigned int reinit_flag : 1; + unsigned int is_bad_cw : 1; + + unsigned int dtu_sid : 8; + unsigned int dtu_timestamp : 8; + + }; + + struct Retx_mode_cfg { + unsigned int res0 :8; + unsigned int invld_range :8; // used for rejecting the too late arrival of the retransmitted DTU + unsigned int buff_size :8; // the total number of cells in playout buffer is 32 * buff_size + unsigned int res1 :7; + unsigned int retx_en :1; + }; + + struct Retx_Tsync_cfg { + unsigned int fw_alpha :16; // number of consecutive HEC error cell causes that the cell delineation state machine transit from SYNC to HUNT (0 means never) + unsigned int sync_inp :16; // reserved + }; + + struct Retx_Td_cfg { + unsigned int res0 :8; + unsigned int td_max :8; // maximum delay between the time a DTU is first created at transmitter and the time the DTU is sent out of ReTX layer at receiver + unsigned int res1 :8; + unsigned int td_min :8; // minimum delay between the time a DTU is first created at transmitter and the time the DTU is sent out of ReTX layer at receiver + }; + + struct Retx_MIB_Timer_cfg { + unsigned int ticks_per_sec : 16; + unsigned int tick_cycle : 16; + }; + + struct DTU_stat_info { + unsigned int complete : 1; + unsigned int bad : 1; + unsigned int res0_0 : 14; + unsigned int time_stamp : 8; + unsigned int cell_cnt : 8; + + unsigned int dtu_rd_ptr : 16; + unsigned int dtu_wr_ptr : 16; + }; + + struct Retx_ctrl_field { + unsigned int res0 : 1; + + unsigned int l2_drop : 1; + unsigned int res1 : 13; + unsigned int retx : 1; + + unsigned int dtu_sid : 8; + unsigned int cell_sid : 8; + }; + + #else + #error Little Endian is not supported yet. + #endif + + struct dsl_param { + unsigned int update_flag; // 00 + unsigned int res0; // 04 + unsigned int MinDelayrt; // 08 + unsigned int MaxDelayrt; // 0C + unsigned int res1; // 10 + unsigned int res2; // 14 + unsigned int RetxEnable; // 18 + unsigned int ServiceSpecificReTx; // 1C + unsigned int res3; // 20 + unsigned int ReTxPVC; // 24 + unsigned int res4; // 28 + unsigned int res5; // 2C + unsigned int res6; // 30 + unsigned int res7; // 34 + unsigned int res8; // 38 + unsigned int res9; // 3C + unsigned int res10; // 40 + unsigned int res11; // 44 + unsigned int res12; // 48 + unsigned int res13; // 4C + unsigned int RxDtuCorruptedCNT; // 50 + unsigned int RxRetxDtuUnCorrectedCNT;// 54 + unsigned int RxLastEFB; // 58 + unsigned int RxDtuCorrectedCNT; // 5C + }; +#endif + + + +#endif // IFXMIPS_ATM_FW_REGS_COMMON_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h new file mode 100644 index 0000000000..5239fce8c9 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h @@ -0,0 +1,178 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_regs_danube.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (Firmware Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_FW_REGS_DANUBE_H +#define IFXMIPS_ATM_FW_REGS_DANUBE_H + + + +/* + * Host-PPE Communication Data Address Mapping + */ +#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001)) +#define CFG_WRX_HTUTS SB_BUFFER(0x2400) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */ +#define CFG_WRX_QNUM SB_BUFFER(0x2401) /* WAN RX Queue Number */ +#define CFG_WRX_DCHNUM SB_BUFFER(0x2402) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */ +#define CFG_WTX_DCHNUM SB_BUFFER(0x2403) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */ +#define CFG_WRDES_DELAY SB_BUFFER(0x2404) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */ +#define WRX_DMACH_ON SB_BUFFER(0x2405) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WTX_DMACH_ON SB_BUFFER(0x2406) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WRX_HUNT_BITTH SB_BUFFER(0x2407) /* WAN RX HUNT Threshold, must be between 2 to 8. */ +#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x2500 + (i) * 20)) +#define WRX_QUEUE_CONTEXT(i) ((struct wrx_queue_context*) SB_BUFFER(0x2504 + (i) * 20)) +#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x2640 + (i) * 7)) +#define WRX_DESC_CONTEXT(i) ((struct wrx_desc_context*) SB_BUFFER(0x2643 + (i) * 7)) +#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x2440 + (i))) +#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x2710 + (i) * 27)) +#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x2711 + (i) * 27)) +#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x2410)) +#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX + #define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2000 + (i))) + #define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2020 + (i))) + #define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2040 + (i))) +#else + #define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x2020 + (i))) + #define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x2040 + (i))) + #define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x2060 + (i))) +#endif + +#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX + + #define RETX_MODE_CFG ((volatile struct Retx_mode_cfg *) SB_BUFFER(0x2408)) + #define RETX_TSYNC_CFG ((volatile struct Retx_Tsync_cfg *) SB_BUFFER(0x2409)) + #define RETX_TD_CFG ((volatile struct Retx_Td_cfg *) SB_BUFFER(0x240A)) + #define RETX_MIB_TIMER_CFG ((volatile struct Retx_MIB_Timer_cfg *) SB_BUFFER(0x240B)) + #define RETX_PLAYOUT_BUFFER_BASE SB_BUFFER(0x240D) + #define RETX_SERVICE_HEADER_CFG SB_BUFFER(0x240E) + #define RETX_MASK_HEADER_CFG SB_BUFFER(0x240F) + + #define RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) PPE_REG_ADDR(0x0D78)) + #define BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AC)) + #define FIRST_BAD_REC_RETX_ADSL_PPE_INTF ((volatile struct Retx_adsl_ppe_intf *) SB_BUFFER(0x23AE)) + + #define PB_BUFFER_USAGE SB_BUFFER(0x2100) + #define DTU_STAT_INFO ((volatile struct DTU_stat_info *) SB_BUFFER(0x2180)) + #define DTU_VLD_STAT SB_BUFFER(0x2380) + + + //===================================================================== + // retx firmware mib, for debug purpose + // address : 0x2388 - 0x238F + // size : 8 + //===================================================================== + #define URETX_RX_TOTAL_DTU SB_BUFFER(0x2388) + #define URETX_RX_BAD_DTU SB_BUFFER(0x2389) + #define URETX_RX_GOOD_DTU SB_BUFFER(0x238A) + #define URETX_RX_CORRECTED_DTU SB_BUFFER(0x238B) + #define URETX_RX_OUTOFDATE_DTU SB_BUFFER(0x238C) + #define URETX_RX_DUPLICATE_DTU SB_BUFFER(0x238D) + #define URETX_RX_TIMEOUT_DTU SB_BUFFER(0x238E) + + #define URETX_ALPHA_SWITCH_TO_HUNT_TIMES SB_BUFFER(0x238F) + + // cell counter for debug purpose + #define WRX_BC0_CELL_NUM SB_BUFFER(0x23E0) + #define WRX_BC0_DROP_CELL_NUM SB_BUFFER(0x23E1) + #define WRX_BC0_NONRETX_CELL_NUM SB_BUFFER(0x23E2) + #define WRX_BC0_RETX_CELL_NUM SB_BUFFER(0x23E3) + #define WRX_BC0_OUTOFDATE_CELL_NUM SB_BUFFER(0x23E4) + #define WRX_BC0_DIRECTUP_NUM SB_BUFFER(0x23E5) + #define WRX_BC0_PBW_TOTAL_NUM SB_BUFFER(0x23E6) + #define WRX_BC0_PBW_SUCC_NUM SB_BUFFER(0x23E7) + #define WRX_BC0_PBW_FAIL_NUM SB_BUFFER(0x23E8) + #define WRX_BC1_CELL_NUM SB_BUFFER(0x23E9) + + // debug info (interface) + + #define DBG_DTU_INTF_WRPTR SB_BUFFER(0x2390) + #define DBG_INTF_FCW_DUP_CNT SB_BUFFER(0x2391) + #define DBG_INTF_SID_CHANGE_IN_DTU_CNT SB_BUFFER(0x2392) + #define DBG_INTF_LCW_DUP_CNT SB_BUFFER(0x2393) + + #define DBG_RFBI_DONE_INT_CNT SB_BUFFER(0x2394) + #define DBG_DREG_BEG_END SB_BUFFER(0x2395) + #define DBG_RFBI_BC0_INVALID_CNT SB_BUFFER(0x2396) + #define DBG_RFBI_LAST_T SB_BUFFER(0x2397) + + #define DBG_RFBI_INTV0 SB_BUFFER(0x23EE) + #define DBG_RFBI_INTV1 SB_BUFFER(0x23EF) + + #define DBG_INTF_INFO(i) ((volatile struct Retx_adsl_ppe_intf_rec *) SB_BUFFER(0x23F0 + i)) + + // Internal status + #define URetx_curr_time SB_BUFFER(0x2398) + #define URetx_sec_counter SB_BUFFER(0x2399) + #define RxCURR_EFB SB_BUFFER(0x239A) + #define RxDTURetransmittedCNT SB_BUFFER(0x239B) + + //===================================================================== + // standardized MIB counter + // address : 0x239C - 0x239F + // size : 4 + //===================================================================== + #define RxLastEFBCNT SB_BUFFER(0x239C) + #define RxDTUCorrectedCNT SB_BUFFER(0x239D) + #define RxDTUCorruptedCNT SB_BUFFER(0x239E) + #define RxRetxDTUUncorrectedCNT SB_BUFFER(0x239F) + + + //===================================================================== + // General URetx Context + // address : 0x23A0 - 0x23AF + // size : 16 + //===================================================================== + #define NEXT_DTU_SID_OUT SB_BUFFER(0x23A0) + #define LAST_DTU_SID_IN SB_BUFFER(0x23A1) + #define NEXT_CELL_SID_OUT SB_BUFFER(0x23A2) + #define ISR_CELL_ID SB_BUFFER(0x23A3) + #define PB_CELL_SEARCH_IDX SB_BUFFER(0x23A4) + #define PB_READ_PEND_FLAG SB_BUFFER(0x23A5) + #define RFBI_FIRST_CW SB_BUFFER(0x23A6) + #define RFBI_BAD_CW SB_BUFFER(0x23A7) + #define RFBI_INVALID_CW SB_BUFFER(0x23A8) + #define RFBI_RETX_CW SB_BUFFER(0x23A9) + #define RFBI_CHK_DTU_STATUS SB_BUFFER(0x23AA) + + //===================================================================== + // per PVC counter for RX error_pdu and correct_pdu + // address : 0x23B0 - 0x23CF + // size : 32 + //===================================================================== + #define WRX_PER_PVC_CORRECT_PDU_BASE SB_BUFFER(0x23B0) + #define WRX_PER_PVC_ERROR_PDU_BASE SB_BUFFER(0x23C0) + + #define __WRXCTXT_L2_RdPtr(i) SB_BUFFER(0x2422 + (i)) + #define __WRXCTXT_L2Pages(i) SB_BUFFER(0x2424 + (i)) + + #define __WTXCTXT_TC_WRPTR(i) SB_BUFFER(0x2450 + (i)) + #define __WRXCTXT_PortState(i) SB_BUFFER(0x242A + (i)) + +#endif + + + +#endif // IFXMIPS_ATM_FW_REGS_DANUBE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h new file mode 100644 index 0000000000..edefe92d25 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_regs_vr9.h @@ -0,0 +1,59 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_fw_regs_vr9.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (Firmware Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_FW_REGS_VR9_H +#define IFXMIPS_ATM_FW_REGS_VR9_H + + + +/* + * Host-PPE Communication Data Address Mapping + */ +#define FW_VER_ID ((volatile struct fw_ver_id *) SB_BUFFER(0x2001)) +#define CFG_WRX_HTUTS SB_BUFFER(0x2010) /* WAN RX HTU Table Size, must be configured before enable PPE firmware. */ +#define CFG_WRX_QNUM SB_BUFFER(0x2011) /* WAN RX Queue Number */ +#define CFG_WRX_DCHNUM SB_BUFFER(0x2012) /* WAN RX DMA Channel Number, no more than 8, must be configured before enable PPE firmware. */ +#define CFG_WTX_DCHNUM SB_BUFFER(0x2013) /* WAN TX DMA Channel Number, no more than 16, must be configured before enable PPE firmware. */ +#define CFG_WRDES_DELAY SB_BUFFER(0x2014) /* WAN Descriptor Write Delay, must be configured before enable PPE firmware. */ +#define WRX_DMACH_ON SB_BUFFER(0x2015) /* WAN RX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WTX_DMACH_ON SB_BUFFER(0x2016) /* WAN TX DMA Channel Enable, must be configured before enable PPE firmware. */ +#define WRX_HUNT_BITTH SB_BUFFER(0x2017) /* WAN RX HUNT Threshold, must be between 2 to 8. */ +#define WRX_QUEUE_CONFIG(i) ((struct wrx_queue_config*) SB_BUFFER(0x4C00 + (i) * 20)) /* i < 16 */ +#define WRX_DMA_CHANNEL_CONFIG(i) ((struct wrx_dma_channel_config*) SB_BUFFER(0x4F80 + (i) * 7)) /* i < 8 */ +#define WTX_PORT_CONFIG(i) ((struct wtx_port_config*) SB_BUFFER(0x4FB8 + (i))) /* i < 2 */ +#define WTX_QUEUE_CONFIG(i) ((struct wtx_queue_config*) SB_BUFFER(0x3A00 + (i) * 27)) /* i < 16 */ +#define WTX_DMA_CHANNEL_CONFIG(i) ((struct wtx_dma_channel_config*) SB_BUFFER(0x3A01 + (i) * 27)) /* i < 16 */ +#define WAN_MIB_TABLE ((struct wan_mib_table*) SB_BUFFER(0x4EF0)) +#define HTU_ENTRY(i) ((struct htu_entry*) SB_BUFFER(0x26A0 + (i))) /* i < 32 */ +#define HTU_MASK(i) ((struct htu_mask*) SB_BUFFER(0x26C0 + (i))) /* i < 32 */ +#define HTU_RESULT(i) ((struct htu_result*) SB_BUFFER(0x26E0 + (i))) /* i < 32 */ + +#define UTP_CFG SB_BUFFER(0x2018) // bit 0~3 - 0x0F: in showtime, 0x00: not in showtime + + + +#endif // IFXMIPS_ATM_FW_REGS_VR9_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_fw_vr9.h b/package/system/ltq-dsl/src/ifxmips_atm_fw_vr9.h new file mode 100644 index 0000000000..5627a5099f --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_fw_vr9.h @@ -0,0 +1,427 @@ +#ifndef IFXMIPS_ATM_FW_VR9_H
+#define IFXMIPS_ATM_FW_VR9_H
+
+
+/******************************************************************************
+**
+** FILE NAME : ifxmips_atm_fw_vr9.h
+** PROJECT : UEIP
+** MODULES : ATM (ADSL)
+**
+** DATE : 22 OCT 2007
+** AUTHOR : Xu Liang
+** DESCRIPTION : ATM Driver (PP32 Firmware)
+** COPYRIGHT : Copyright (c) 2006
+** Infineon Technologies AG
+** Am Campeon 1-12, 85579 Neubiberg, Germany
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** HISTORY
+** $Date $Author $Comment
+** 22 OCT 2007 Xu Liang Initial Version, v00.01
+*******************************************************************************/
+
+
+#define VER_IN_FIRMWARE 1
+
+#define ATM_FW_VER_MAJOR 0
+#define ATM_FW_VER_MINOR 24
+
+
+static u32 firmware_binary_code[] = {
+ 0x800004B8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000FFE0, 0x00000000, 0x00000000, 0x00000000,
+ 0xC1000002, 0xD90C00F8, 0xC2000002, 0xDA0800F9, 0x80004390, 0xC2000000, 0xDA0800F9, 0x80003A10,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x800039C8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x80004B60, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x800038C8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400000, 0xC000ABC0, 0xC88400F8, 0x80004050, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC0400002, 0xC000ABC0, 0xC88400F8, 0x80003FD0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3C00004, 0xDBC800F9, 0xC10C0002, 0xD90C00F8, 0x8000FEE0, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC10E0002, 0xD90C00F8, 0xC0004028, 0xC84000F8, 0x80004000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x900004D9, 0x00000000, 0x00000000, 0x00000000, 0x90CC0481,
+ 0x00000000, 0x00000000, 0x00000000, 0xC3C00000, 0xDBC800F9, 0xC1400008, 0xC1900000, 0x71588000,
+ 0x14100100, 0xC140000A, 0xC1900002, 0x71588000, 0x14100100, 0xC140000C, 0xC1900004, 0x71588000,
+ 0x14100100, 0xC1400004, 0xC1900006, 0x71588000, 0x14100100, 0xC1400006, 0xC1900008, 0x71588000,
+ 0x14100100, 0xC140000E, 0xC190000A, 0x71588000, 0x14100100, 0xC1400000, 0xC190000C, 0x71588000,
+ 0x14100100, 0xC1400002, 0xC190000E, 0x71588000, 0x14100100, 0xC0400000, 0xC11C0000, 0xC000E82C,
+ 0xCD05CE00, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC0400002, 0xC11C0000, 0xC000E82C, 0xCD05CE00,
+ 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC000E824, 0x00000000, 0xCBC000F9, 0xCB8000F9, 0xCB4000F9,
+ 0xCB0000F8, 0xC000ABE4, 0x5BFC4000, 0xCFC000F9, 0x5BB84000, 0xCF8000F9, 0x5B744000, 0xCF4000F9,
+ 0x5B304000, 0xCF0000F8, 0xC000EA10, 0x00000000, 0xCBC000F9, 0xCB8000F8, 0xC000ABE0, 0x5BFC4000,
+ 0xCFC000F9, 0x5BB84000, 0xCF8000F8, 0xC30001FE, 0xC000F416, 0xCF0000F8, 0xC3000000, 0x7F018000,
+ 0xC000E42E, 0xCF0000F8, 0xC000E40E, 0xCF0000F8, 0xC3C1FFFE, 0xC000690E, 0xCFC00078, 0xC000692C,
+ 0xCFC00078, 0xC0006924, 0xCFC00038, 0xC0006912, 0xCFC00038, 0xC0006966, 0xCFC00038, 0xC0006968,
+ 0xCFC00078, 0xC000696A, 0xCFC00078, 0xC3C00000, 0xC2800020, 0xC3000000, 0x7F018000, 0x6FF88000,
+ 0x6FD44000, 0x4395C000, 0x5BB89800, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFC8, 0x00000000,
+ 0xC3C00000, 0xC2800010, 0x6FF86000, 0x47BDC000, 0x5BB89F00, 0xC3400000, 0x58380004, 0xCB420078,
+ 0x00000000, 0x58380008, 0xCF400078, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0xC3C00000, 0xC2800020,
+ 0xC348001E, 0xC3000000, 0x7F018000, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400,
+ 0x58380008, 0xCF408418, 0x5838000A, 0xCF0000F8, 0x5BFC0002, 0xB7E8FFB0, 0x00000000, 0x00000000,
+ 0xC3E0E282, 0x5BFC0030, 0xC0004002, 0xCFC000F8, 0xC000E82C, 0xC11E0002, 0xCD01EF00, 0xC000E82E,
+ 0xCD01EF00, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x80000028, 0x00000000, 0x80001CB8,
+ 0x00000000, 0x8000FFE0, 0xC0006918, 0xD28000F8, 0xC2000000, 0xDF600038, 0x5E600020, 0x84000272,
+ 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000402A, 0xCA0000F8, 0xC0006912,
+ 0xCA4000F8, 0xC0006924, 0xCA8000F8, 0xC0006966, 0xCAC000F8, 0x00000000, 0xC121FFFE, 0x5911FE94,
+ 0x14100000, 0x76250000, 0x76290000, 0x762D0000, 0x840001CA, 0xC0006918, 0xCA4000F8, 0xC28001FE,
+ 0x76290000, 0x5A640002, 0x6A254010, 0x5EE80000, 0x8400001A, 0x6AA54000, 0x80000010, 0xC62800F8,
+ 0x62818008, 0xC0006918, 0xCF0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC0006966,
+ 0xCA4000F8, 0xC2000002, 0x6A310000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE,
+ 0x5911FE94, 0x14100000, 0x6F346000, 0x4771A000, 0x5B749F00, 0xC2800000, 0x58340006, 0xCA800078,
+ 0xC2C00000, 0x58340000, 0xCAC000D8, 0xC2400000, 0x5834000A, 0xCA420078, 0x6EA82000, 0x42E9E000,
+ 0x6F2CA000, 0x42E56000, 0x5AEC3200, 0xC3990040, 0xC7381C18, 0xC6F80060, 0x99005560, 0xDB9800F8,
+ 0xDBD800F9, 0x00000000, 0xDEA000F8, 0x46310000, 0x8400FD80, 0xC0006958, 0xC84000F8, 0x00000000,
+ 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC000ABC8, 0xCB8400F8, 0xC000ABC4, 0xC88400F8, 0x5FB80000,
+ 0x8400FCFA, 0xC000FAC0, 0xCA0400F8, 0x00000000, 0x00000000, 0xA6040070, 0xC000ABE4, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x98C05CD8,
+ 0xC000697C, 0xCA0000F8, 0x59640004, 0xC0004030, 0xCA0000F8, 0xC2400002, 0x6A452000, 0x76250000,
+ 0x8400FC3A, 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCA0000F8, 0xC42400F8,
+ 0x00000000, 0xA63C17DA, 0x00000000, 0xC000ABE4, 0xC80400F8, 0x6C908000, 0x45088000, 0x45088000,
+ 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0xC0006934, 0xCE0000F8, 0xC2800002, 0xC4681C08,
+ 0xC62821D0, 0xC2600010, 0x5A650D80, 0xC0004020, 0xCB4000F8, 0xC2200400, 0x5A200D40, 0xC7601040,
+ 0xC000F220, 0xCE8000F8, 0xC000F200, 0xCE4000F8, 0xC000F202, 0xCE0000F8, 0xC000F240, 0xCB4000F8,
+ 0x00000000, 0x00000000, 0xA754FFE0, 0xC2000000, 0xC7600040, 0xA7520042, 0x00000000, 0x00000000,
+ 0x99005FD8, 0xC0009DE2, 0xC94000F8, 0xC1800002, 0x80001680, 0x58204DC0, 0xC2000000, 0xCA000018,
+ 0xC2400000, 0xCA414000, 0xC2800000, 0xCA812000, 0xC2C00000, 0xCAC20018, 0xC0006938, 0xCE0000F8,
+ 0xC0006920, 0xCE4000F8, 0xC0006916, 0xCE8000F8, 0xC0006922, 0xCEC000F8, 0xA6400540, 0x00000000,
+ 0xC0006938, 0xCBC000F8, 0x00000000, 0xC3800000, 0x6FF48000, 0x6FD44000, 0x4355A000, 0x5B749800,
+ 0x58340000, 0xCB802010, 0x00000000, 0xC2000000, 0x6FB46000, 0x4779A000, 0x5B749F00, 0x5834000C,
+ 0xCA000020, 0xC000691A, 0xCF8000F8, 0x5E200000, 0x8400046A, 0xC2000000, 0xDF610048, 0x5E6001E8,
+ 0x8800FFE8, 0xC2000002, 0xC2400466, 0xC2A00000, 0x5AA80000, 0xC000F006, 0xCE0000F8, 0xC000F008,
+ 0xCE4000F8, 0xC000F00A, 0xCE8000F8, 0x99004FA0, 0xC1A0FFFE, 0xC000E824, 0xC9840070, 0xC0006934,
+ 0xCA4000F8, 0xC2000000, 0xC2800002, 0x99004FE0, 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0x990050C8, 0xC000691A, 0xC94000F8, 0x00000000, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0xC0006922, 0xCA001118, 0xC3C00000, 0xC3800000, 0xC0006930,
+ 0xCE023118, 0xC0006932, 0xCBC000D8, 0xC2800000, 0xC000691E, 0xCFC000F8, 0xC000ABDE, 0xCA800060,
+ 0xC3A0001A, 0x5BB94000, 0xC6B80060, 0xC000691C, 0xCF8000F8, 0x99005338, 0xC000691C, 0xC1400000,
+ 0xC9420048, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0xC2000000, 0xC1220002, 0xD90C00F8,
+ 0xDF600038, 0x5E600020, 0x8400FFF2, 0xC000691C, 0xCA0000F8, 0xC000691E, 0xCA4000F8, 0x00000000,
+ 0x00000000, 0x99005560, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0xC2000000, 0xDF610048, 0x5E6001FE,
+ 0x8800FFE8, 0xC0006916, 0xCA8000F8, 0xC2C00000, 0xDFEC0048, 0xC2400000, 0x466D2000, 0x8400004A,
+ 0x5EA80000, 0x8400003A, 0xC2600002, 0x99005FD8, 0xC0009DEE, 0xC94000F8, 0xC1800002, 0x80000030,
+ 0xC2600000, 0x99005FD8, 0xC0009DEC, 0xC94000F8, 0xC1800002, 0xC2000068, 0xC6240078, 0xC0006930,
+ 0xCE400080, 0xC000691A, 0xC98000F8, 0xC000ABDE, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC9F00,
+ 0x990053C0, 0xD95800F8, 0xD99800F9, 0xD9D400F8, 0x99005338, 0xC000691C, 0xC1400000, 0xC9420048,
+ 0xC2000000, 0xDF600038, 0x5E600020, 0x8400FFEA, 0x00000000, 0xC000691C, 0xCA0000F8, 0xC000691E,
+ 0xCA4000F8, 0x00000000, 0x00000000, 0x99005560, 0xDA1800F8, 0xDA5800F9, 0x00000000, 0x800010E8,
+ 0x00000000, 0x99005FD8, 0xC0009DEA, 0xC94000F8, 0xC1800002, 0x800010B8, 0xC0006938, 0xCBC000F8,
+ 0x00000000, 0x00000000, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0x58380008, 0xCA0000F8,
+ 0x00000000, 0x00000000, 0xA6000382, 0x00000000, 0xC0006938, 0xCBC000F8, 0xC3000000, 0x00000000,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0x58380000, 0xCB002010, 0xC2000000, 0x58380008,
+ 0xCA020078, 0x5838000C, 0xCAC000F8, 0x5838000E, 0xCA4000F8, 0xC000691A, 0xCF0000F8, 0xC0006930,
+ 0xCEC000F8, 0xC000693C, 0xCE0000F8, 0xC0006932, 0xCE4000F8, 0x5E200000, 0x84000120, 0xC2800000,
+ 0xA6FE00BA, 0x6F206000, 0x46310000, 0x5A209F00, 0x5820000C, 0xCA800020, 0x00000000, 0x00000000,
+ 0x5EA80000, 0x840001F2, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x990050C8,
+ 0xC000691A, 0xC94000F8, 0x00000000, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0xC0006930,
+ 0xCAC000F8, 0xC0006932, 0xCA4000F8, 0xC7EC1118, 0xC0006930, 0xCEC000F8, 0x5838000C, 0xCEC000F8,
+ 0x58000002, 0xCE4000F8, 0xC0006934, 0xCA0000F8, 0xC2400002, 0x6E642000, 0x6E642000, 0x76612000,
+ 0x8400002A, 0xC2400002, 0x6E684000, 0x58380008, 0xCE804200, 0xA6000020, 0x6E682000, 0x58380008,
+ 0xCE802100, 0xC2400002, 0x6E642000, 0x76612000, 0x840000EA, 0x58380008, 0xCA0000F8, 0xC2800000,
+ 0xC2400000, 0xA60200C0, 0xDBA800F8, 0x6F386000, 0x47B1C000, 0x5BB89F00, 0x58380004, 0xCA400078,
+ 0x58380002, 0xCA800078, 0x00000000, 0xDEB800F8, 0x46A54000, 0x88000060, 0x00000000, 0xC0009DE4,
+ 0xCA0000F8, 0xC2400002, 0x6E640000, 0x5A200002, 0xCE0000F8, 0x58380008, 0xCE400000, 0x80000018,
+ 0x00000000, 0x80000048, 0xC0006934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020C6A, 0x00000000,
+ 0x00000000, 0x80000C98, 0xC2800000, 0xC2000080, 0xC240001A, 0xDF690048, 0x46294000, 0x46A54000,
+ 0x8800FFD2, 0xC2000006, 0xC2600982, 0x5A643B6E, 0x5838000A, 0xCA8000F8, 0xC000F006, 0xCE0000F8,
+ 0xC000F008, 0xCE4000F8, 0xC000F00A, 0xCE8000F8, 0x99004FA0, 0xC1A0FFFE, 0xC000E824, 0xC9840070,
+ 0xC2000000, 0xC0006930, 0xCA02E008, 0x58380026, 0xCA4000F8, 0x00000000, 0xC2800000, 0x99004FE0,
+ 0xDA9800F8, 0xC61400F8, 0xC65800F8, 0xC0006934, 0xCA0000F8, 0x00000000, 0x00000000, 0xA6020022,
+ 0x00000000, 0x00000000, 0x80000318, 0xC0006938, 0xCBC000F8, 0xC000ABE4, 0xC80400F8, 0x6C908000,
+ 0x45088000, 0x45088000, 0x40100000, 0xCA0000F8, 0xC42400F8, 0x00000000, 0x58240018, 0xCA0000F8,
+ 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800, 0xC3000000, 0xC3400002, 0xC2C00000, 0xC62C0078,
+ 0xC6270038, 0xC0006940, 0xCE400038, 0xC6260038, 0xC0006942, 0xCE400038, 0xC000693C, 0xCA0000F8,
+ 0x5EEC0000, 0x8400018A, 0x5A6C0010, 0x46254000, 0x88000190, 0x5A600052, 0x46E54000, 0x88000178,
+ 0x58380006, 0xCA8000F8, 0xC0006940, 0xCA0000F8, 0xC2400000, 0xC6A70038, 0x7E412000, 0x76612000,
+ 0xC2000000, 0xC6A10038, 0x46250000, 0x84000138, 0xC0006942, 0xCA0000F8, 0xC2400000, 0xC6A60038,
+ 0x7E412000, 0x76612000, 0xC2000000, 0xC6A00038, 0x58380002, 0xCA8000F8, 0x46250000, 0x840000E8,
+ 0xC2400000, 0xC6A60078, 0x466D0000, 0x880000DA, 0xC2400000, 0xC6A40078, 0x58380008, 0xCA8000F8,
+ 0x46E50000, 0x880000BA, 0x00000000, 0xA6820018, 0x00000000, 0xC7700B00, 0xA6840098, 0x00000000,
+ 0xC7700A00, 0x80000080, 0xC7700200, 0xC000693C, 0xCAC000F8, 0x80000060, 0xC7700300, 0xC000693C,
+ 0xCAC000F8, 0x80000040, 0xC7700900, 0x80000030, 0xC7700800, 0x80000020, 0xC7700700, 0x80000010,
+ 0xC7700500, 0xC0006944, 0xCF0000F8, 0xC000693E, 0xCEC000F8, 0xC0006938, 0xCA4000F8, 0xC000693C,
+ 0xCB8000F8, 0xC000693E, 0xCB4000F8, 0xC3000000, 0x6E608000, 0x6E544000, 0x42150000, 0x5A209800,
+ 0x5AA00008, 0x58200004, 0xCB000078, 0xC0006934, 0xCA0000F8, 0xC2400000, 0xC0006930, 0xCA42E008,
+ 0xC3C00018, 0xA6020098, 0x00000000, 0x43656000, 0x47AD0000, 0x88000050, 0x46F96000, 0x6EE04010,
+ 0x5BE00004, 0xC2000000, 0xC6E00008, 0x5E200000, 0x84000042, 0x5BFC0002, 0x80000030, 0xC3C00004,
+ 0x5A2C0008, 0x47A10000, 0x88000012, 0x5FB80008, 0x6FE04000, 0x42390000, 0x47212000, 0x88000068,
+ 0xC2400000, 0xC0006930, 0xCA42E008, 0xC2060002, 0xC68000F8, 0xCE006300, 0x6FE04000, 0x4721C000,
+ 0x5F700010, 0x4765A000, 0xC2000000, 0xC6340008, 0xC25A000A, 0xC000691A, 0xCA401C18, 0xC2800000,
+ 0xC0006932, 0xCA8000D8, 0xC000ABDE, 0xCA400060, 0x6FA04010, 0x42290000, 0xC000691E, 0xCE0000F8,
+ 0xC7E41048, 0xC000691C, 0xCE4000F8, 0x6FE04000, 0x43A1C000, 0xC000693C, 0xCF8000F8, 0xC000693E,
+ 0xCF4000F8, 0xC000693A, 0xCFC000F8, 0x80000008, 0x00000000, 0x00000000, 0x00000000, 0xC2000000,
+ 0xDCE000F8, 0xA622FFD8, 0xC1220002, 0xD90C00F8, 0xC0006938, 0xCBC000F8, 0xC0006944, 0xCB4000F8,
+ 0xC000ABDE, 0xCB0000F8, 0xC0006934, 0xCA0000F8, 0x6FF88000, 0x6FD44000, 0x4395C000, 0x5BB89800,
+ 0xA6020268, 0xC2400000, 0x58380008, 0xCA406000, 0xDFE800F8, 0xC2218E08, 0x5A21BAF6, 0x46A14000,
+ 0x84000022, 0xC2080002, 0x7361A000, 0x80000058, 0x5E640000, 0x84000022, 0xC20C0002, 0x7361A000,
+ 0x80000030, 0xC2000000, 0xC760E710, 0xC7604218, 0x5E200000, 0x84000272, 0xC2200002, 0xC0006930,
+ 0xCE021000, 0x99005FD8, 0xC0009DE8, 0xC94000F8, 0xC1800002, 0x58380000, 0xCA0000F8, 0x00000000,
+ 0x00000000, 0xA6000132, 0xC0006940, 0xCA8000F8, 0xC0006942, 0xCA4000F8, 0xC7600078, 0xC6A01838,
+ 0xC6601038, 0xC000693A, 0xCA4000F8, 0xC0006934, 0xCA8000F8, 0xC000AB40, 0x40300000, 0x40240000,
+ 0x5C000004, 0x5EC0ABC0, 0x88000012, 0x5C000080, 0xCE0000F8, 0x58000002, 0x5EC0ABC0, 0x88000012,
+ 0x5C000080, 0xCE8000F8, 0xC000693E, 0xCA0000F8, 0xC2400000, 0x5838000C, 0xCE4000F8, 0x99005FD8,
+ 0xC0009DF0, 0xC94000F8, 0xC61800F8, 0xC0006930, 0xC6100078, 0xCD000078, 0x800000A8, 0xC2400002,
+ 0x58380008, 0xCE400000, 0xC0006944, 0xCF4000F8, 0x80000278, 0xC000693C, 0xCA4000F8, 0xDFE800F8,
+ 0x5A300018, 0xC000AB40, 0x40200000, 0xCA0000F8, 0x58380008, 0xC6501078, 0xCD021078, 0x5838000A,
+ 0xCE8000F8, 0x58380026, 0xCE0000F8, 0xC0006944, 0xCF4000F8, 0x99005338, 0xC000691C, 0xC1400000,
+ 0xC9420048, 0x80000038, 0x00000000, 0x99005FD8, 0xC0009DE6, 0xC94000F8, 0xC1800002, 0x8000FDD8,
+ 0xC2000000, 0xC2400020, 0xDF600038, 0xB624FFEA, 0xC000691C, 0xCA4000F8, 0xC000691E, 0xCA8000F8,
+ 0x99005560, 0xDA5800F8, 0xDA9800F9, 0x00000000, 0xC0006934, 0xCA0000F8, 0x00000000, 0xC2800000,
+ 0xA6020160, 0xC2400004, 0xC2000080, 0xDF690048, 0x46294000, 0x46A54000, 0x8800FFDA, 0x00000000,
+ 0xC000691A, 0xC98000F8, 0xC000ABDE, 0xC94000F8, 0x6D9C6000, 0x45D8E000, 0x59DC9F00, 0x990053C0,
+ 0xD95800F8, 0xD99800F9, 0xD9D400F8, 0x99005338, 0xC000691C, 0xC1400000, 0xC9420048, 0xC2000000,
+ 0xC2400020, 0xDF600038, 0xB624FFEA, 0xC000691C, 0xCA4000F8, 0xC000691E, 0xCA8000F8, 0x99005560,
+ 0xDA5800F8, 0xDA9800F9, 0x00000000, 0x58380008, 0xCA4000F8, 0xC2000000, 0xCE000018, 0xC2A1FFFE,
+ 0x5AA9FFFE, 0xCE021078, 0x5838000A, 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0xC000E838, 0xC2500002, 0xCE450800, 0xC000ABC8, 0xCB8400F8, 0xC2000000, 0xC000E82C, 0xCA040038,
+ 0x5FB80002, 0xC000ABC8, 0xCF8400F8, 0x58880002, 0xB6080018, 0x00000000, 0xC0800000, 0xC000ABC4,
+ 0xCC8400F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x8000E350, 0xC2000000, 0xDF600038,
+ 0x5E200020, 0x8400026A, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000402C,
+ 0xCA0000F8, 0xC0006910, 0xCA4000F8, 0xC000692C, 0xCA8000F8, 0xC0006968, 0xCAC000F8, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0x76250000, 0x76290000, 0x76E16000, 0x840001C2, 0xC0006926,
+ 0xCA4000F8, 0xC201FFFE, 0x76E16000, 0x5A640002, 0x6AE50010, 0x5F200000, 0x8400001A, 0x6A250000,
+ 0x80000010, 0xC6E000F8, 0x62014008, 0xC0006926, 0xCE8000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000,
+ 0x00000000, 0xC0006968, 0xCA4000F8, 0xC2000002, 0x6A290000, 0x7E010000, 0x76612000, 0xCE4000F8,
+ 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6EB4A000, 0x6E944000, 0x4755A000, 0x4769A000,
+ 0x5B747400, 0x58340002, 0xC2000000, 0xCA0000D8, 0x5834002E, 0xC2400000, 0xCA400078, 0x6EB0A000,
+ 0x6EBC4000, 0x473D8000, 0x47298000, 0x5B30342E, 0x5B300004, 0x6E642000, 0x4225E000, 0xC39A8024,
+ 0xC7380060, 0xC6B81C18, 0x99005560, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC2000000, 0xDF600038,
+ 0x5E200020, 0x840002A2, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E,
+ 0xCA0000F8, 0xC000692A, 0xCA4000F8, 0xC000696A, 0xCB0000F8, 0xC0006956, 0xCAC000F8, 0x00000000,
+ 0xC121FFFE, 0x5911FE94, 0x14100000, 0x77218000, 0x77258000, 0x84000202, 0xC201FFFE, 0x77218000,
+ 0x5AEC0002, 0x6B2D0010, 0x5EA00000, 0x8400001A, 0x6A2D0000, 0x80000010, 0xC72000F8, 0x62016008,
+ 0xC0006956, 0xCEC000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000696A, 0xCA4000F8,
+ 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94,
+ 0x14100000, 0x6EF4A000, 0x6ED44000, 0x4755A000, 0x476DA000, 0x5B747400, 0x5834000E, 0xC2000000,
+ 0xCA0000D8, 0x58340008, 0xC2400000, 0xCA420078, 0x5834000C, 0xC2800000, 0xCA832010, 0x6E644010,
+ 0x42250000, 0x4229E000, 0xC39A8008, 0x58340008, 0xCB809018, 0x58340008, 0xC2800000, 0xCA810010,
+ 0x6EE0A000, 0x6EE44000, 0x46250000, 0x462D0000, 0x5A200008, 0x5A203408, 0x42290000, 0xC6380060,
+ 0xC6F81C18, 0x99005560, 0xDB9800F8, 0xDBD800F9, 0x00000000, 0xC000695A, 0xC84000F8, 0x00000000,
+ 0xC3C00002, 0x787C2000, 0xCC4000F8, 0xC0004030, 0xCA0000F8, 0xC2400008, 0x6A452000, 0x76250000,
+ 0x84000E02, 0xC000EA28, 0xC3800000, 0xCB840038, 0xC000EA14, 0xC3400000, 0xCB440038, 0xC0009F70,
+ 0xCB0400F8, 0xB7B4005A, 0x5804F802, 0xCAC000F8, 0xA7000060, 0x00000000, 0x00000000, 0xA6C8DD30,
+ 0xC2800000, 0xC6E80018, 0x80000070, 0x00000000, 0x00000000, 0x00000000, 0x8000DCF8, 0x00000000,
+ 0xC2800000, 0xC7282018, 0xC000690E, 0xCA4000F8, 0x6BE9E000, 0x00000000, 0x767D2000, 0x8400DCB0,
+ 0x6EA0A000, 0x6E944000, 0x46150000, 0x46290000, 0x5A207400, 0x5820000C, 0xCA0000F8, 0xC0006946,
+ 0xCE8000F8, 0xA6220368, 0x00000000, 0xC2200060, 0xC0006948, 0xCE000008, 0xCE021038, 0xC240000A,
+ 0xC000694A, 0xCE4000F8, 0xC2B60002, 0xC0006964, 0xCE837B00, 0x99005830, 0xC0009F74, 0xC88400F8,
+ 0x00000000, 0xC0006946, 0xCBC000F8, 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, 0x4795C000,
+ 0x47BDC000, 0x5BB87400, 0x990055F0, 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99005338, 0xC000691C,
+ 0xC1400000, 0xC9420048, 0xC000691C, 0x990057E8, 0xC94000F9, 0xC98000F8, 0x00000000, 0x99005560,
+ 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0x99005228,
+ 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6FF8A000,
+ 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400, 0x58380010, 0xCA0000F8, 0xC000ABE0, 0xC80400F8,
+ 0x6C908000, 0x45088000, 0x45088000, 0x40100000, 0xCA4000F8, 0xC43400F8, 0x00000000, 0xC74000F8,
+ 0xCE0000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002,
+ 0x6ABD4000, 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x99005FD8,
+ 0xC0009DF6, 0xC94000F8, 0xC1800002, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0x00000000,
+ 0xC1220002, 0xD90C00F8, 0xC2000000, 0xC000EA14, 0xCA040038, 0xC000EA28, 0xC2500002, 0xCE450800,
+ 0x58880002, 0xB6080018, 0xC0009F74, 0xC0800000, 0xCC8400F8, 0x8000D900, 0xC0006946, 0xCBC000F8,
+ 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002, 0x6ABD4000,
+ 0x72692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x6FF8A000, 0x6FD44000,
+ 0x4795C000, 0x47BDC000, 0x5BB87400, 0x58380008, 0xCA0000F8, 0x5838000C, 0xCA4000F8, 0xC3400000,
+ 0xC6340000, 0xC000694E, 0xCF4000F8, 0xC2800000, 0xC62A0078, 0xC3000000, 0xC6308018, 0x6F304000,
+ 0x43298000, 0xC000693C, 0xCF0000F8, 0xC2C00000, 0xC66C0078, 0xC0006950, 0xCEC000F8, 0xC2800000,
+ 0xC66AE020, 0xC0006954, 0xCE8000F8, 0x5F740000, 0x840001A0, 0x5E300028, 0x46E12000, 0x8400016A,
+ 0x46E12000, 0x88000132, 0x5E300018, 0x46E12000, 0x8800002A, 0x46E12000, 0x84000042, 0x00000000,
+ 0x800000C0, 0x00000000, 0x99005970, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC3400002, 0xC000694E,
+ 0xCF4000F8, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000, 0xC000690E, 0xCA4000F8, 0xC2800002,
+ 0x6ABD4000, 0x7E814000, 0x76692000, 0xCE4000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000,
+ 0xC2200060, 0xC0006948, 0xCE021038, 0xC2000000, 0xC000694C, 0xCE0000F8, 0x80000080, 0x00000000,
+ 0x99005970, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0x99005B70, 0xDBD800F8, 0xDB9800F9, 0xC78000F8,
+ 0xC2200058, 0xC0006948, 0xCE021038, 0xC2000002, 0xC000694C, 0xCE0000F8, 0xC2000006, 0xC000F006,
+ 0xCE0000F8, 0x5838000A, 0xCA4000F8, 0xC2200982, 0x5A203B6E, 0xC000F008, 0xCE0000F8, 0xC000F00A,
+ 0xCE4000F8, 0xC0006954, 0xCA8000F8, 0xC200000C, 0xC000694A, 0xCE0000F8, 0xC0006948, 0xCE800008,
+ 0xC2B60000, 0xC0006964, 0xCE8000F8, 0x99005830, 0xC0009F74, 0xC88400F8, 0x00000000, 0xC0006946,
+ 0xCBC000F8, 0xC000694C, 0xCA0000F8, 0x6FF8A000, 0x6FD44000, 0x4795C000, 0x47BDC000, 0x5BB87400,
+ 0x5E200000, 0x840000FA, 0x00000000, 0x990055F0, 0xDBD800F8, 0xDB9800F9, 0x00000000, 0x99005338,
+ 0xC000691C, 0xC1400000, 0xC9420048, 0xC000691C, 0x990057E8, 0xC94000F9, 0xC98000F8, 0x00000000,
+ 0x99005560, 0xD95800F8, 0xD99800F9, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x14140000, 0x00000000,
+ 0x99005228, 0xDBD800F8, 0xDB9800F9, 0xC7D800F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000,
+ 0xC000693C, 0xCA8000F8, 0xC000694E, 0xCAC000F8, 0xC3000018, 0xC3400006, 0x5E200000, 0x8400002A,
+ 0xC2800000, 0xC2C00000, 0xC300001E, 0xC3400000, 0xC6AC1078, 0xC72C0418, 0xC76C0810, 0x58380010,
+ 0xCA8000F8, 0x58380008, 0xCEC000F8, 0xC6280100, 0xC000ABE0, 0xC80400F8, 0x6C908000, 0x45088000,
+ 0x45088000, 0x40100000, 0xCB0000F8, 0xC43400F8, 0x00000000, 0xC74000F8, 0xCE8000F8, 0xC0006952,
+ 0xCE8000F8, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFE8, 0x00000000, 0xC000694C, 0xCA0000F8,
+ 0xC0006950, 0xCAC000F8, 0x5E200000, 0x8400006A, 0xDFE800F8, 0x7E814000, 0x5834001A, 0xCE8000F8,
+ 0x99005FD8, 0xC0009DF4, 0xC94000F8, 0xC1800002, 0x99005FD8, 0xC0009DF8, 0xC94000F8, 0xC6D800F8,
+ 0xC1220002, 0xD90C00F8, 0x5E200000, 0x84000040, 0x5838002C, 0xCB0000F8, 0xDFE800F8, 0x00000000,
+ 0x58380014, 0xCF0000F8, 0x80000018, 0xC2A1FFFE, 0x5AA9FFFE, 0x5838000A, 0xCE8000F8, 0xC3000000,
+ 0xC000EA14, 0xCB040038, 0xC2D00002, 0xC000EA28, 0xCEC50800, 0xC000694E, 0xCA8000F8, 0x58880002,
+ 0xB4B00018, 0xC0009F74, 0xC0800000, 0xCC8400F8, 0x5EA80000, 0x84000152, 0x5E200000, 0x84000140,
+ 0xC000693C, 0xCA8000F8, 0x00000000, 0x00000000, 0x5AA80060, 0xCE8000F8, 0x99005970, 0xDBD800F8,
+ 0xDB9800F9, 0xC78000F8, 0x99005B70, 0xDBD800F8, 0xDB9800F9, 0xC78000F8, 0xC0006952, 0xCAC000F8,
+ 0x58380000, 0xCA8000F8, 0xC30C0002, 0xC7F00018, 0xA6800098, 0x00000000, 0x00000000, 0xC161FFFE,
+ 0x5955FFFE, 0x14140000, 0x00000000, 0xC000F800, 0xCA0000F8, 0x00000000, 0x00000000, 0xA60CFFEA,
+ 0xC6F00500, 0xC6B0C400, 0xCF0000F8, 0x00000000, 0xC121FFFE, 0x5911FE94, 0x14100000, 0x8000CFB0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000CF48, 0xDCBC00F9, 0x5FFC0000, 0x84000052,
+ 0xC3800002, 0xDB8800F9, 0x5FFC0004, 0x8400C86A, 0xC3800000, 0xDB8800F9, 0xC3CE0002, 0xC000E800,
+ 0xCFC0E700, 0xC3E1FFFE, 0x597DFFFE, 0x593DFE14, 0x94000001, 0x00000000, 0x00000000, 0x00000000,
+ 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC43800F8, 0x00000000,
+ 0xC000402E, 0xCA0000F8, 0xC000ABD8, 0xCB4400F8, 0x00000000, 0x00000000, 0x47610000, 0x880000B0,
+ 0x00000000, 0xA7C00048, 0xC000ABD4, 0xC1000002, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00,
+ 0x800000D8, 0x00000000, 0xA7D20120, 0x00000000, 0xC7E14040, 0xC2400000, 0xC6246028, 0xC200006A,
+ 0x46250000, 0xC6240030, 0xC000E810, 0xCE440030, 0x8000FF70, 0xC2000000, 0xC000E808, 0xCA040010,
+ 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x5A200002, 0x5E600010, 0x84000010, 0xC2000000, 0xC000E808,
+ 0xCE040010, 0xC3400000, 0x80000010, 0x5B740002, 0xC000ABD8, 0xCF4400F8, 0x99004F78, 0xC000ABC8,
+ 0xC94400F8, 0xC1800000, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0x80000600, 0x5B740002, 0xC000ABD8,
+ 0xCF4400F8, 0xC78000F8, 0xC13C0002, 0xCD03DE00, 0xC000ABC8, 0xC94400F8, 0xC1800000, 0xC000E82C,
+ 0xC9840038, 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB4980580, 0x00000000, 0xC0800000,
+ 0x80000568, 0xC000ABE8, 0xC80400F8, 0x00000000, 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8,
+ 0x00000000, 0xA7C00130, 0xC000ABCC, 0xCA0400F8, 0xC2400000, 0xC000FAEC, 0xCA440018, 0x5A200002,
+ 0xC000ABCC, 0xCE0400F8, 0xB624008A, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC000ABC8, 0xC94400F8,
+ 0xC1800000, 0xC000E82C, 0xC9840038, 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB4980470,
+ 0x00000000, 0xC0800000, 0x80000458, 0xC000ABD4, 0xC1000004, 0xCD0400F8, 0xC000E820, 0xC2000002,
+ 0xCE0400F8, 0xC2000000, 0xC000ABCC, 0xCE0400F8, 0xC000ABD8, 0xCE0400F8, 0x8000FF28, 0xC000ABD4,
+ 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x99004F78, 0xC000ABC8, 0xC94400F8,
+ 0xC1800000, 0xC1200000, 0xC000E818, 0xCD061000, 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC2000000,
+ 0xC000ABCC, 0xCE0400F8, 0x80000358, 0xC000FAC0, 0xCB8400F8, 0xC000ABE8, 0xC80400F8, 0x00000000,
+ 0x00000000, 0x40080000, 0xCBC000F8, 0xC42800F8, 0x00000000, 0x00000000, 0xC68000F8, 0xC13C0000,
+ 0xCD03DE00, 0xA780024A, 0x00000000, 0x00000000, 0xA7C0020A, 0x00000000, 0xC000FB60, 0xC2060006,
+ 0xCE046308, 0xA7E801C2, 0x00000000, 0xC000ABD0, 0xCA0400F8, 0xC2400000, 0xC000FAEC, 0xCA448018,
+ 0x5A200002, 0xC000ABD0, 0xCE0400F8, 0xB62400AA, 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00,
+ 0xC000FACC, 0xC2000002, 0xCE040000, 0xC000ABC8, 0xC94400F8, 0xC1800000, 0xC000E82C, 0xC9840038,
+ 0x59540002, 0xC000ABC8, 0xCD4400F8, 0x58880002, 0xB49801C8, 0x00000000, 0xC0800000, 0x800001B0,
+ 0xC000ABD4, 0xC1000000, 0xCD0400F8, 0xC11C0000, 0xC000E82C, 0xCD05CE00, 0x99004F78, 0xC000ABC8,
+ 0xC94400F8, 0xC1800000, 0xC2000000, 0xC000E820, 0xCE0400F8, 0xC1200000, 0xC000E818, 0xCD061000,
+ 0xC11C0002, 0xC000E82C, 0xCD05CE00, 0xC000ABD0, 0xCE0400F8, 0xC2000002, 0xC000FACC, 0xCE040008,
+ 0x800000E8, 0xC2000002, 0xC000ABD0, 0xCE0400F8, 0x8000FE88, 0xC2000000, 0xC000ABD0, 0xCE0400F8,
+ 0xA7E60032, 0x00000000, 0xC2000002, 0xC000FB60, 0xCE040000, 0x8000FE70, 0x00000000, 0xA7860052,
+ 0x00000000, 0xC68000F8, 0xC13C0002, 0xCD03DE00, 0xC2020002, 0xC7E2A540, 0xC000FB60, 0xCE0400F8,
+ 0x8000FE18, 0xC2040002, 0xC000FB60, 0xCE044200, 0x8000FDF8, 0xC2C80002, 0x6AC56000, 0xDACC00F8,
+ 0xC000ABD4, 0xCB4400F8, 0xC000ABC8, 0xCB8400F8, 0xC000E838, 0xC3C00000, 0xCBC40038, 0x5EF40004,
+ 0x84000022, 0xC3000000, 0xC000FACC, 0xCF042100, 0x47F98000, 0x8400002A, 0x47F98000, 0x88000030,
+ 0xC1006E8C, 0x8000BCB8, 0xC000ABC0, 0xCC8400F8, 0x8000F6C8, 0xC000FAC0, 0xCAC400F8, 0xC000ABD4,
+ 0xCB4400F8, 0xA6C0FBD2, 0x00000000, 0x5EF40000, 0x8400F722, 0x5EF40002, 0x8400F99A, 0x5EF40004,
+ 0x8400FB9A, 0xC1006CE8, 0x8000BC30, 0x00000000, 0xC0800000, 0xDF4B0038, 0xC0006900, 0xCB8000F8,
+ 0xC2000000, 0xC000690A, 0xA78000D0, 0xCBC000F8, 0xC1000000, 0xD90000F9, 0xC1000002, 0xD90C00F8,
+ 0x6FF46000, 0x477DA000, 0x5B749F00, 0xC2400000, 0x58340004, 0xCA400078, 0xC0006900, 0xCE000000,
+ 0x5A640002, 0x58340004, 0xC6500078, 0xCD000078, 0xC0006914, 0xCA4000F8, 0xC2000002, 0x6A3D0000,
+ 0x72612000, 0xCE4000F8, 0xC000E408, 0xCE0000F8, 0xA78200D8, 0xC0006908, 0xCBC000F8, 0xC1000000,
+ 0xD90000F9, 0xC1000002, 0xD90C00F8, 0x6FF4A000, 0x6FD44000, 0x4755A000, 0x477DA000, 0x5B747400,
+ 0xC2800000, 0x58340006, 0xCA800078, 0xC2000000, 0xC0006900, 0xCE002100, 0x5EA80002, 0x58340006,
+ 0xC6900078, 0xCD000078, 0x5A7C0020, 0xC2000002, 0x6A250000, 0xC000E408, 0xCE0000F8, 0xDCA800F9,
+ 0x5EA80000, 0x8400BAA0, 0x00000000, 0xA4800230, 0x00000000, 0xC3C00000, 0xC000F418, 0xCBC00018,
+ 0xC3400000, 0xC2400000, 0x6FF86000, 0x47BDC000, 0x5BB89F00, 0x58380008, 0xCB400078, 0x58380006,
+ 0xCA400078, 0x5F740002, 0x58380008, 0xC7500078, 0xCD000078, 0xC2000000, 0x58380004, 0xCA020078,
+ 0xC3000000, 0x5838000C, 0xCB000020, 0x5A640002, 0x46610000, 0x84000010, 0xC2400000, 0x58380006,
+ 0xC6500078, 0xCD000078, 0xC2000000, 0x5838000A, 0xCA020078, 0x5B300002, 0x5838000C, 0xC7100020,
+ 0xCD000020, 0xC2420020, 0x5A200004, 0x46252000, 0x84000010, 0xC2000000, 0x5838000A, 0xC6101078,
+ 0xCD021078, 0xC0006966, 0xCA4000F8, 0xC2000002, 0x6A3D0000, 0x72612000, 0xCE4000F8, 0x5F740000,
+ 0x84000040, 0xC0006912, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8,
+ 0x5F300020, 0x84000040, 0xC0006924, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000,
+ 0xCE0000F8, 0xA4820070, 0xC2400000, 0xC000F418, 0xCA408018, 0xC2000002, 0xC0006900, 0xCE000000,
+ 0xC000690A, 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xA4840270,
+ 0x00000000, 0xC3C00000, 0xC000F418, 0xCBC10018, 0xC2800000, 0xC2000000, 0x6FF8A000, 0x6FD44000,
+ 0x4795C000, 0x47BDC000, 0x5BB87400, 0x5838002E, 0xCA800078, 0x58380006, 0xCA020078, 0xC3400000,
+ 0x5838002E, 0xCB420078, 0x5AA80002, 0x46A10000, 0x84000010, 0xC2800000, 0x5838002E, 0xC6900078,
+ 0xCD000078, 0x5F740002, 0x5838002E, 0xC7501078, 0xCD021078, 0xC0006968, 0xCA4000F8, 0xC2000002,
+ 0x6A3D0000, 0x72612000, 0xCE4000F8, 0xC000692A, 0xCA8000F8, 0x5E740000, 0x84000040, 0xC0006910,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0x6ABD4010, 0xA68000BA,
+ 0x00000000, 0x58380032, 0xCA0000F8, 0x58000002, 0xCA4000F8, 0x5838000C, 0x00000000, 0xCE0000F9,
+ 0xCE4000F8, 0xC000692A, 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0xC000692C,
+ 0xCA0000F8, 0xC2C00002, 0x6AFD6000, 0x722D0000, 0xCE0000F8, 0x80000040, 0xC000692C, 0xCA0000F8,
+ 0xC2C00002, 0x6AFD6000, 0x7EC16000, 0x762D0000, 0xCE0000F8, 0xA4880120, 0xC2C00000, 0xC000F418,
+ 0xCAC20018, 0xC000690E, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x7E010000, 0x76612000, 0xCE4000F8,
+ 0xC000696A, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0x6EF0A000, 0x6ED44000,
+ 0x47158000, 0x472D8000, 0x5B307400, 0x58300000, 0xCA0000F8, 0x00000000, 0xC2400002, 0x76612000,
+ 0x8400004A, 0xC24C0002, 0xC6E40018, 0xC624C400, 0x58300010, 0xCA400500, 0x00000000, 0xC000F800,
+ 0xCE4000F8, 0xA4860070, 0xC2400000, 0xC000F418, 0xCA418018, 0xC2020002, 0xC0006900, 0xCE002100,
+ 0xC0006908, 0xCE4000F8, 0xC1000000, 0xD90000F9, 0xD8400078, 0xC1000004, 0xD90000F9, 0xC000F414,
+ 0xCC8000F8, 0xC10E0002, 0xD90C00F8, 0x8000EDF0, 0xDFBC00F9, 0xC000696E, 0x99005C80, 0xC94000F8,
+ 0xC7D800F8, 0x00000000, 0xC57000F8, 0x5EF00020, 0x88000148, 0x6F346000, 0x4771A000, 0x5B749F00,
+ 0x58340008, 0xC2400000, 0xCA400078, 0x00000000, 0xC2000000, 0x5A640002, 0xCE400078, 0x58340004,
+ 0xCA000078, 0x00000000, 0x00000000, 0x5E200002, 0xCE000078, 0xC0006912, 0xCA8000F8, 0xC2400002,
+ 0x6A712000, 0x72A54000, 0xCE8000F8, 0x5E200000, 0x84000052, 0xC000402A, 0xCA0000F8, 0xC000E408,
+ 0xCA8000F8, 0x76250000, 0x00000000, 0x72A14000, 0xCE8000F8, 0x80000038, 0xC0006914, 0xCA0000F8,
+ 0x7E412000, 0x00000000, 0x76250000, 0xCE0000F8, 0x800000D0, 0x6EF4A000, 0x6ED44000, 0x4755A000,
+ 0x476DA000, 0x5B747400, 0x5834002E, 0xC2400000, 0xCA420078, 0x00000000, 0xC2000000, 0x5A640002,
+ 0xC6501078, 0xCD021078, 0x58340006, 0xCA000078, 0x00000000, 0x00000000, 0x5A200002, 0xCE000078,
+ 0xC0006910, 0xCA4000F8, 0xC2000002, 0x6A2D0000, 0x72612000, 0xCE4000F8, 0xC2000002, 0x6A310000,
+ 0xC000E42A, 0xCE0000F8, 0xC1040002, 0xD90C00F8, 0x00000000, 0x8000EB60, 0x00000000, 0xC4980928,
+ 0x9D000000, 0xC5580038, 0xC000E838, 0xCD8400F8, 0xC1440080, 0xC1C06B40, 0xC55C0F80, 0xC000F00E,
+ 0x9D000000, 0xCD8000F8, 0xC000F00C, 0xCDC000F8, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0x00000000,
+ 0xD9D800F9, 0xC000AB40, 0x401C0000, 0x5DC0ABC0, 0x88000012, 0x5C000080, 0xCD8000F8, 0xC1F0000A,
+ 0x715CA000, 0xDD9800F8, 0xDD9C00F9, 0x41D8E000, 0xC5D40260, 0xC000F010, 0xCD4000F8, 0x6C9C8000,
+ 0x45C8E000, 0x45C8E000, 0x59DC0004, 0xC1601260, 0xC5D40260, 0x9D000000, 0xC000F012, 0xCD4000F8,
+ 0x00000000, 0x00000000, 0xD95800F8, 0x6D586000, 0x4594C000, 0x59989F00, 0xD99800F9, 0x5818000A,
+ 0xC1800000, 0xC9800078, 0xC0007200, 0x6D5CA000, 0x401C0000, 0x40180000, 0xC94000F8, 0x58000002,
+ 0x00000000, 0xC9C000F8, 0xC0006930, 0xCD4000F8, 0xC0006932, 0xCDC000F8, 0x59980004, 0xC1C20020,
+ 0xB59C0018, 0x00000000, 0xC1800000, 0xDD9C00F9, 0x581C000A, 0xCD800078, 0x581C000C, 0xC1800000,
+ 0xC9800020, 0xC1C00002, 0xDD9400F8, 0x69D4E000, 0x5D980002, 0xCD800020, 0xC0006924, 0xC98000F8,
+ 0x00000000, 0x9D000000, 0x00000000, 0x719CC000, 0xCD8000F8, 0xC000692A, 0xC94000F8, 0xC1C00002,
+ 0x69D8E000, 0x7DC0C000, 0x7558A000, 0xCD4000F8, 0xC000692C, 0xC94000F8, 0xDD8000F9, 0x58000032,
+ 0x755CA000, 0x84000090, 0xC94000F9, 0xC98000F8, 0xDD8000F9, 0x5800000C, 0x00000000, 0xCD4000F9,
+ 0xCD8000F8, 0xC000692C, 0xC94000F8, 0xC000692A, 0xC98000F8, 0x715CA000, 0xC000692C, 0xCD4000F8,
+ 0x719CC000, 0xC000692A, 0xCD8000F8, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC000ABDE,
+ 0xC98000F8, 0x00000000, 0xC1C00080, 0x4194C000, 0x459CE000, 0x88000012, 0xC5D800F8, 0xC000ABDE,
+ 0xCD8000F8, 0xC000F406, 0xC98000F8, 0xC1C00002, 0x9D000000, 0xC5D80A00, 0xC5581048, 0xCD8000F8,
+ 0xC0006930, 0xC98000F8, 0xC0006932, 0xC9C000F8, 0xC140000E, 0xC5581C18, 0xDD9400F8, 0xC000AB40,
+ 0x40140000, 0x5D40ABC0, 0x88000012, 0x5C000080, 0xCD8000F8, 0x58000002, 0x5D40ABC0, 0x88000012,
+ 0x5C000080, 0xCDC000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078, 0xC1800000, 0x58140000,
+ 0xC98000D8, 0x6DDC2000, 0xC000691E, 0x41D8E000, 0xCDC000F8, 0xDD9800F8, 0xC1C00022, 0xC5D80D70,
+ 0xDD9400F9, 0xC5581C18, 0xC000691C, 0xCD8000F8, 0xDD5400F8, 0xC1C00000, 0x58140006, 0xC9C20078,
+ 0xC1800000, 0x58140004, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010, 0xC1C00000,
+ 0x9D000000, 0x58140006, 0xC5D81078, 0xCD821078, 0xC000ABDC, 0xC94000F8, 0xC1820020, 0xC1D00002,
+ 0x5814AB00, 0xD58000F8, 0x58000002, 0xD58000F9, 0x59540004, 0xB5580018, 0xC000ABDC, 0xC1400000,
+ 0xCD4000F8, 0xDD9800F9, 0x9D000000, 0xDD9400F8, 0xC000F402, 0xCDC10800, 0xC1C00000, 0xC1800080,
+ 0x5D980004, 0xDF5D0048, 0x459CA000, 0x8800FFF2, 0xDD8000F9, 0x5800000C, 0x00000000, 0xC94000F9,
+ 0xC98000F8, 0xC1C00002, 0xC5D43F00, 0xC5D81E00, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0x00000000,
+ 0x581CAB40, 0x5DC0ABC0, 0x88000012, 0x5C000080, 0xCD4000F8, 0x58000002, 0x5DC0ABC0, 0x88000012,
+ 0x5C000080, 0xCD8000F8, 0xC000ABDE, 0xC9C000F8, 0x00000000, 0xC15004C0, 0xC5D40060, 0xDD9C00F8,
+ 0xC5D41C18, 0xC1C00000, 0xDD8000F9, 0x58000030, 0xC9C00078, 0xDD8000F9, 0x58000002, 0xC98000F8,
+ 0x6DDC2000, 0xC000691C, 0x41D8E000, 0xCD4000F9, 0xCDC000F8, 0xDD9400F9, 0xC1C00000, 0x58140030,
+ 0xC9C00078, 0xC1800000, 0x58140006, 0xC9820078, 0x00000000, 0x59DC0002, 0x45D8C000, 0x84000010,
+ 0xC1C00000, 0x9D000000, 0x58140030, 0xC5D80078, 0xCD800078, 0xC1C00000, 0xDF5C0038, 0x5DDC0020,
+ 0x8400FFEA, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0xC160FFFE, 0xC000EA10,
+ 0xC9440070, 0xC1A0FFFE, 0x59983408, 0xC000F00C, 0xCD4000F8, 0xC000F00E, 0xCD8000F8, 0xC0006964,
+ 0xC98000F8, 0x00000000, 0xC170000A, 0x7158A000, 0x6C988000, 0x4588C000, 0x4588C000, 0x59980004,
+ 0xC5940270, 0xC000F010, 0xCD4000F8, 0xC0006946, 0xC94000F8, 0x00000000, 0x00000000, 0x6D58A000,
+ 0x6D5C4000, 0x459CC000, 0x4594C000, 0xC000694A, 0xC94000F8, 0xC0006948, 0xC9C000F8, 0x4194C000,
+ 0xC1400012, 0xC55C1818, 0x9D000000, 0xC59C0268, 0xC000F012, 0xCDC000F8, 0xC1400000, 0x58000012,
+ 0xC9410038, 0xC0006950, 0xC9C000F8, 0xC55800F8, 0xC5940838, 0xC5581078, 0xD99400F8, 0xC000693C,
+ 0xC94000F8, 0xC0006954, 0xC98000F8, 0x59DC00A8, 0x45D4E000, 0x41D8E000, 0x5D5C0030, 0x88000010,
+ 0xC1C00030, 0xC1800000, 0xC5D84028, 0xC1400000, 0xC5D40008, 0x5DD40002, 0x84000072, 0x5DD40004,
+ 0x8400009A, 0x5DD40006, 0x840000C2, 0x5DD80026, 0x840000EA, 0xDD5400F8, 0xDD8000F9, 0x58000008,
+ 0x40180000, 0xCD4000F8, 0x59980002, 0x8000FFC0, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000,
+ 0xCD4000B8, 0x59980002, 0x8000FF88, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400078,
+ 0x59980002, 0x8000FF50, 0xDD5400F8, 0xDD8000F9, 0x58000008, 0x40180000, 0xCD400038, 0x59980002,
+ 0x8000FF18, 0x00000000, 0x9D000000, 0x00000000, 0x00000000, 0x00000000, 0x58000012, 0xC94000F8,
+ 0xC0006954, 0xC9C000F8, 0xC0006950, 0xC9400078, 0xDD8000F9, 0x58000028, 0x5D9C0000, 0x84000052,
+ 0x5D9C0002, 0x84000052, 0x5D9C0004, 0x8400006A, 0xC55B0038, 0xC55C08B8, 0xCD800039, 0xCDC108B8,
+ 0x80000060, 0xCD4000F8, 0x80000050, 0xC55900B8, 0xC55C1838, 0xCD8000B9, 0xCDC31838, 0x80000028,
+ 0xC55A0078, 0xC55C1078, 0xCD800079, 0xCDC21078, 0x9D000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x59540002, 0x6994E018, 0x61C0C008, 0x4194A000, 0x5D940040, 0x88000012, 0xC59400F8, 0x9D000000,
+ 0xCD4000F8, 0x00000000, 0x00000000, 0xC000697E, 0xCA4000F8, 0xC0000000, 0xC55800F8, 0xC9D400F9,
+ 0x00000000, 0x00000000, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0,
+ 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550,
+ 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000,
+ 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9,
+ 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8,
+ 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9,
+ 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8,
+ 0xC52160A0, 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0,
+ 0xC5241550, 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550,
+ 0x79E08000, 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0x79E08000,
+ 0xCD1800F9, 0xC5D000F8, 0xC9D400F9, 0xC66000F8, 0xC52160A0, 0xC5241550, 0xC000697C, 0x9CC00000,
+ 0xCE0000F8, 0xC000697E, 0xCE4000F8, 0x9D000000, 0x4158A000, 0xCD4000F8, 0x00000000,
+};
+
+static u32 firmware_binary_data[] = {
+};
+
+
+#endif // IFXMIPS_ATM_FW_VR9_H
+
diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h b/package/system/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h new file mode 100644 index 0000000000..b9ba2c7ebd --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ppe_amazon_se.h @@ -0,0 +1,94 @@ +#ifndef IFXMIPS_ATM_PPE_AMAZON_SE_H +#define IFXMIPS_ATM_PPE_AMAZON_SE_H + + + +/* + * FPI Configuration Bus Register and Memory Address Mapping + */ +#define IFX_PPE (KSEG1 | 0x1E180000) +#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2))) +#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2))) +#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2))) +#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2))) +#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2))) +#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2))) +#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2))) +#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2))) +#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2))) +#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2))) +#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2))) +#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8200) << 2))) +#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8C00) << 2))) +#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2))) + +/* + * DWORD-Length of Memory Blocks + */ +#define PP32_DEBUG_REG_DWLEN 0x0030 +#define PPM_INT_REG_DWLEN 0x0010 +#define PP32_INTERNAL_RES_DWLEN 0x00C0 +#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800) +#define PPE_REG_DWLEN 0x1000 +#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1) +#define PPM_INT_UNIT_DWLEN 0x0100 +#define PPM_TIMER0_DWLEN 0x0100 +#define PPM_TASK_IND_REG_DWLEN 0x0100 +#define PPS_BRK_DWLEN 0x0100 +#define PPM_TIMER1_DWLEN 0x0100 +#define SB_RAM0_DWLEN 0x0A00 +#define SB_RAM1_DWLEN 0x0A00 +#define QSB_CONF_REG_DWLEN 0x0100 + +/* + * PP32 to FPI Address Mapping + */ +#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x2200) && ((__sb_addr) <= 0x2BFF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2200) : \ + (((__sb_addr) >= 0x2C00) && ((__sb_addr) <= 0x35FF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2C00) : \ + 0)) + +/* + * PP32 Debug Control Register + */ +#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0, 0x0000) + +#define DBG_CTRL_RESTART 0 +#define DBG_CTRL_STOP 1 + +#define PP32_HALT_STAT PP32_DEBUG_REG_ADDR(0, 0x0D00) +#define PP32_BREAKPOINT_REASONS PP32_DEBUG_REG_ADDR(0, 0x0A00) + +#define PP32_BRK_SRC PP32_DEBUG_REG_ADDR(0, 0x0F00) + +#define PP32_DBG_CUR_PC PP32_DEBUG_REG_ADDR(0, 0x0F80) + +#define PP32_DBG_TASK_NO PP32_DEBUG_REG_ADDR(0, 0x0F81) + +/* + * Share Buffer + */ +#define SB_MST_PRI0 PPE_REG_ADDR(0x0300) +#define SB_MST_PRI1 PPE_REG_ADDR(0x0301) + +/* + * EMA Registers + */ +#define EMA_CMDCFG PPE_REG_ADDR(0x0A00) +#define EMA_DATACFG PPE_REG_ADDR(0x0A01) +#define EMA_CMDCNT PPE_REG_ADDR(0x0A02) +#define EMA_DATACNT PPE_REG_ADDR(0x0A03) +#define EMA_ISR PPE_REG_ADDR(0x0A04) +#define EMA_IER PPE_REG_ADDR(0x0A05) +#define EMA_CFG PPE_REG_ADDR(0x0A06) +#define EMA_SUBID PPE_REG_ADDR(0x0A07) + +#define EMA_ALIGNMENT 4 + +/* + * Mailbox IGU1 Interrupt + */ +#define PPE_MAILBOX_IGU1_INT (INT_NUM_IM2_IRL0 + 13) + + + +#endif // IFXMIPS_ATM_PPE_AMAZON_SE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ppe_ar9.h b/package/system/ltq-dsl/src/ifxmips_atm_ppe_ar9.h new file mode 100644 index 0000000000..5c5bfa8260 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ppe_ar9.h @@ -0,0 +1,188 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_ppe_ar9.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PPE Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_PPE_AR9_H +#define IFXMIPS_ATM_PPE_AR9_H + + + +/* + * FPI Configuration Bus Register and Memory Address Mapping + */ +#define IFX_PPE (KSEG1 | 0x1E180000) +#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2))) +#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2))) +#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2))) +#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2))) +#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2))) +#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2))) +#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2))) +#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2))) +#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2))) +#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2))) +#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2))) +#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8000) << 2))) +#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8800) << 2))) +#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9000) << 2))) +#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9800) << 2))) +#define SB_RAM4_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xA000) << 2))) +#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2))) + +/* + * DWORD-Length of Memory Blocks + */ +#define PP32_DEBUG_REG_DWLEN 0x0030 +#define PPM_INT_REG_DWLEN 0x0010 +#define PP32_INTERNAL_RES_DWLEN 0x00C0 +#define CDM_CODE_MEMORYn_DWLEN(n) 0x1000 +#define PPE_REG_DWLEN 0x1000 +#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1) +#define PPM_INT_UNIT_DWLEN 0x0100 +#define PPM_TIMER0_DWLEN 0x0100 +#define PPM_TASK_IND_REG_DWLEN 0x0100 +#define PPS_BRK_DWLEN 0x0100 +#define PPM_TIMER1_DWLEN 0x0100 +#define SB_RAM0_DWLEN 0x0800 +#define SB_RAM1_DWLEN 0x0800 +#define SB_RAM2_DWLEN 0x0800 +#define SB_RAM3_DWLEN 0x0800 +#define SB_RAM4_DWLEN 0x0C00 +#define QSB_CONF_REG_DWLEN 0x0100 + +/* + * PP32 to FPI Address Mapping + */ +#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x0000) && ((__sb_addr) <= 0x0FFF)) ? PPE_REG_ADDR((__sb_addr)): \ + (((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x27FF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \ + (((__sb_addr) >= 0x2800) && ((__sb_addr) <= 0x2FFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2800) : \ + (((__sb_addr) >= 0x3000) && ((__sb_addr) <= 0x37FF)) ? SB_RAM2_ADDR((__sb_addr) - 0x3000) : \ + (((__sb_addr) >= 0x3800) && ((__sb_addr) <= 0x3FFF)) ? SB_RAM3_ADDR((__sb_addr) - 0x3800) : \ + (((__sb_addr) >= 0x4000) && ((__sb_addr) <= 0x4BFF)) ? SB_RAM4_ADDR((__sb_addr) - 0x4000) : \ + 0)) + +/* + * PP32 Debug Control Register + */ +#define NUM_OF_PP32 1 + +#define PP32_DBG_CTRL(n) PP32_DEBUG_REG_ADDR(n, 0x0000) + +#define DBG_CTRL_RESTART 0 +#define DBG_CTRL_STOP 1 + +#define PP32_CTRL_CMD(n) PP32_DEBUG_REG_ADDR(n, 0x0B00) + #define PP32_CTRL_CMD_RESTART (1 << 0) + #define PP32_CTRL_CMD_STOP (1 << 1) + #define PP32_CTRL_CMD_STEP (1 << 2) + #define PP32_CTRL_CMD_BREAKOUT (1 << 3) + +#define PP32_CTRL_OPT(n) PP32_DEBUG_REG_ADDR(n, 0x0C00) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_ON (3 << 0) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_OFF (2 << 0) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_ON (3 << 2) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_OFF (2 << 2) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN_ON (3 << 4) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN_OFF (2 << 4) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON (3 << 6) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF (2 << 6) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP(n) (*PP32_CTRL_OPT(n) & (1 << 0)) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 2)) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 4)) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT(n) (*PP32_CTRL_OPT(n) & (1 << 6)) + +#define PP32_BRK_PC(n, i) PP32_DEBUG_REG_ADDR(n, 0x0900 + (i) * 2) +#define PP32_BRK_PC_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0901 + (i) * 2) +#define PP32_BRK_DATA_ADDR(n, i) PP32_DEBUG_REG_ADDR(n, 0x0904 + (i) * 2) +#define PP32_BRK_DATA_ADDR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0905 + (i) * 2) +#define PP32_BRK_DATA_VALUE_RD(n, i) PP32_DEBUG_REG_ADDR(n, 0x0908 + (i) * 2) +#define PP32_BRK_DATA_VALUE_RD_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0909 + (i) * 2) +#define PP32_BRK_DATA_VALUE_WR(n, i) PP32_DEBUG_REG_ADDR(n, 0x090C + (i) * 2) +#define PP32_BRK_DATA_VALUE_WR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x090D + (i) * 2) + #define PP32_BRK_CONTEXT_MASK(i) (1 << (i)) + #define PP32_BRK_CONTEXT_MASK_EN (1 << 4) + #define PP32_BRK_COMPARE_GREATER_EQUAL (1 << 5) // valid for break data value rd/wr only + #define PP32_BRK_COMPARE_LOWER_EQUAL (1 << 6) + #define PP32_BRK_COMPARE_EN (1 << 7) + +#define PP32_BRK_TRIG(n) PP32_DEBUG_REG_ADDR(n, 0x0F00) + #define PP32_BRK_GRPi_PCn_ON(i, n) ((3 << ((n) * 2)) << ((i) * 16)) + #define PP32_BRK_GRPi_PCn_OFF(i, n) ((2 << ((n) * 2)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_ADDRn_ON(i, n) ((3 << ((n) * 2 + 4)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_ADDRn_OFF(i, n) ((2 << ((n) * 2 + 4)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_RDn_ON(i, n) ((3 << ((n) * 2 + 8)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_RDn_OFF(i, n)((2 << ((n) * 2 + 8)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_WRn_ON(i, n) ((3 << ((n) * 2 + 12)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_WRn_OFF(i, n)((2 << ((n) * 2 + 12)) << ((i) * 16)) + #define PP32_BRK_GRPi_PCn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n))) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_ADDRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 2)) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_VALUE_RDn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 4)) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_VALUE_WRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 6)) << ((i) * 8))) + +#define PP32_CPU_STATUS(n) PP32_DEBUG_REG_ADDR(n, 0x0D00) +#define PP32_HALT_STAT(n) PP32_CPU_STATUS(n) +#define PP32_DBG_CUR_PC(n) PP32_CPU_STATUS(n) + #define PP32_CPU_USER_STOPPED(n) (*PP32_CPU_STATUS(n) & (1 << 0)) + #define PP32_CPU_USER_BREAKIN_RCV(n) (*PP32_CPU_STATUS(n) & (1 << 1)) + #define PP32_CPU_USER_BREAKPOINT_MET(n) (*PP32_CPU_STATUS(n) & (1 << 2)) + #define PP32_CPU_CUR_PC(n) (*PP32_CPU_STATUS(n) >> 16) + +#define PP32_BREAKPOINT_REASONS(n) PP32_DEBUG_REG_ADDR(n, 0x0A00) + #define PP32_BRK_PC_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << (i))) + #define PP32_BRK_DATA_ADDR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 2))) + #define PP32_BRK_DATA_VALUE_RD_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 4))) + #define PP32_BRK_DATA_VALUE_WR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 6))) + #define PP32_BRK_DATA_VALUE_RD_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 8))) + #define PP32_BRK_DATA_VALUE_RD_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 9))) + #define PP32_BRK_DATA_VALUE_WR_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 12))) + #define PP32_BRK_DATA_VALUE_WR_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 13))) + #define PP32_BRK_CUR_CONTEXT(n) ((*PP32_BREAKPOINT_REASONS(n) >> 16) & 0x03) + +#define PP32_GP_REG_BASE(n) PP32_DEBUG_REG_ADDR(n, 0x0E00) +#define PP32_GP_CONTEXTi_REGn(n, i, j) PP32_DEBUG_REG_ADDR(n, 0x0E00 + (i) * 16 + (j)) + +/* + * EMA Registers + */ +#define EMA_CMDCFG PPE_REG_ADDR(0x0A00) +#define EMA_DATACFG PPE_REG_ADDR(0x0A01) +#define EMA_CMDCNT PPE_REG_ADDR(0x0A02) +#define EMA_DATACNT PPE_REG_ADDR(0x0A03) +#define EMA_ISR PPE_REG_ADDR(0x0A04) +#define EMA_IER PPE_REG_ADDR(0x0A05) +#define EMA_CFG PPE_REG_ADDR(0x0A06) +#define EMA_SUBID PPE_REG_ADDR(0x0A07) + +#define EMA_ALIGNMENT 4 + +/* + * Mailbox IGU1 Interrupt + */ +#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL0 + 24 + + + +#endif // IFXMIPS_ATM_PPE_AR9_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ppe_common.h b/package/system/ltq-dsl/src/ifxmips_atm_ppe_common.h new file mode 100644 index 0000000000..30b12c80d6 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ppe_common.h @@ -0,0 +1,365 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_ppe_common.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PPE Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_PPE_COMMON_H +#define IFXMIPS_ATM_PPE_COMMON_H +#if defined(CONFIG_DANUBE) + #include "ifxmips_atm_ppe_danube.h" +#elif defined(CONFIG_AMAZON_SE) + #include "ifxmips_atm_ppe_amazon_se.h" +#elif defined(CONFIG_AR9) + #include "ifxmips_atm_ppe_ar9.h" +#elif defined(CONFIG_VR9) + #include "ifxmips_atm_ppe_vr9.h" +#else + #error Platform is not specified! +#endif + + + +/* + * Code/Data Memory (CDM) Interface Configuration Register + */ +#define CDM_CFG PPE_REG_ADDR(0x0100) + +#define CDM_CFG_RAM1 GET_BITS(*CDM_CFG, 3, 2) +#define CDM_CFG_RAM0 (*CDM_CFG & (1 << 1)) + +#define CDM_CFG_RAM1_SET(value) SET_BITS(0, 3, 2, value) +#define CDM_CFG_RAM0_SET(value) ((value) ? (1 << 1) : 0) + +/* + * QSB Internal Cell Delay Variation Register + */ +#define QSB_ICDV QSB_CONF_REG_ADDR(0x0007) + +#define QSB_ICDV_TAU GET_BITS(*QSB_ICDV, 5, 0) + +#define QSB_ICDV_TAU_SET(value) SET_BITS(0, 5, 0, value) + +/* + * QSB Scheduler Burst Limit Register + */ +#define QSB_SBL QSB_CONF_REG_ADDR(0x0009) + +#define QSB_SBL_SBL GET_BITS(*QSB_SBL, 3, 0) + +#define QSB_SBL_SBL_SET(value) SET_BITS(0, 3, 0, value) + +/* + * QSB Configuration Register + */ +#define QSB_CFG QSB_CONF_REG_ADDR(0x000A) + +#define QSB_CFG_TSTEPC GET_BITS(*QSB_CFG, 1, 0) + +#define QSB_CFG_TSTEPC_SET(value) SET_BITS(0, 1, 0, value) + +/* + * QSB RAM Transfer Table Register + */ +#define QSB_RTM QSB_CONF_REG_ADDR(0x000B) + +#define QSB_RTM_DM (*QSB_RTM) + +#define QSB_RTM_DM_SET(value) ((value) & 0xFFFFFFFF) + +/* + * QSB RAM Transfer Data Register + */ +#define QSB_RTD QSB_CONF_REG_ADDR(0x000C) + +#define QSB_RTD_TTV (*QSB_RTD) + +#define QSB_RTD_TTV_SET(value) ((value) & 0xFFFFFFFF) + +/* + * QSB RAM Access Register + */ +#define QSB_RAMAC QSB_CONF_REG_ADDR(0x000D) + +#define QSB_RAMAC_RW (*QSB_RAMAC & (1 << 31)) +#define QSB_RAMAC_TSEL GET_BITS(*QSB_RAMAC, 27, 24) +#define QSB_RAMAC_LH (*QSB_RAMAC & (1 << 16)) +#define QSB_RAMAC_TESEL GET_BITS(*QSB_RAMAC, 9, 0) + +#define QSB_RAMAC_RW_SET(value) ((value) ? (1 << 31) : 0) +#define QSB_RAMAC_TSEL_SET(value) SET_BITS(0, 27, 24, value) +#define QSB_RAMAC_LH_SET(value) ((value) ? (1 << 16) : 0) +#define QSB_RAMAC_TESEL_SET(value) SET_BITS(0, 9, 0, value) + +/* + * QSB Queue Scheduling and Shaping Definitions + */ +#define QSB_WFQ_NONUBR_MAX 0x3f00 +#define QSB_WFQ_UBR_BYPASS 0x3fff +#define QSB_TP_TS_MAX 65472 +#define QSB_TAUS_MAX 64512 +#define QSB_GCR_MIN 18 + +/* + * QSB Constant + */ +#define QSB_RAMAC_RW_READ 0 +#define QSB_RAMAC_RW_WRITE 1 + +#define QSB_RAMAC_TSEL_QPT 0x01 +#define QSB_RAMAC_TSEL_SCT 0x02 +#define QSB_RAMAC_TSEL_SPT 0x03 +#define QSB_RAMAC_TSEL_VBR 0x08 + +#define QSB_RAMAC_LH_LOW 0 +#define QSB_RAMAC_LH_HIGH 1 + +#define QSB_QPT_SET_MASK 0x0 +#define QSB_QVPT_SET_MASK 0x0 +#define QSB_SET_SCT_MASK 0x0 +#define QSB_SET_SPT_MASK 0x0 +#define QSB_SET_SPT_SBVALID_MASK 0x7FFFFFFF + +#define QSB_SPT_SBV_VALID (1 << 31) +#define QSB_SPT_PN_SET(value) (((value) & 0x01) ? (1 << 16) : 0) +#define QSB_SPT_INTRATE_SET(value) SET_BITS(0, 13, 0, value) + +/* + * QSB Queue Parameter Table Entry and Queue VBR Parameter Table Entry + */ +#if defined(__BIG_ENDIAN) + union qsb_queue_parameter_table { + struct { + unsigned int res1 :1; + unsigned int vbr :1; + unsigned int wfqf :14; + unsigned int tp :16; + } bit; + u32 dword; + }; + + union qsb_queue_vbr_parameter_table { + struct { + unsigned int taus :16; + unsigned int ts :16; + } bit; + u32 dword; + }; +#else + union qsb_queue_parameter_table { + struct { + unsigned int tp :16; + unsigned int wfqf :14; + unsigned int vbr :1; + unsigned int res1 :1; + } bit; + u32 dword; + }; + + union qsb_queue_vbr_parameter_table { + struct { + unsigned int ts :16; + unsigned int taus :16; + } bit; + u32 dword; + }; +#endif // defined(__BIG_ENDIAN) + +/* + * Mailbox IGU0 Registers + */ +#define MBOX_IGU0_ISRS PPE_REG_ADDR(0x0200) +#define MBOX_IGU0_ISRC PPE_REG_ADDR(0x0201) +#define MBOX_IGU0_ISR PPE_REG_ADDR(0x0202) +#define MBOX_IGU0_IER PPE_REG_ADDR(0x0203) + +#define MBOX_IGU0_ISRS_SET(n) (1 << (n)) +#define MBOX_IGU0_ISRC_CLEAR(n) (1 << (n)) +#define MBOX_IGU0_ISR_ISR(n) (*MBOX_IGU0_ISR & (1 << (n))) +#define MBOX_IGU0_IER_EN(n) (*MBOX_IGU0_IER & (1 << (n))) +#define MBOX_IGU0_IER_EN_SET(n) (1 << (n)) + +/* + * Mailbox IGU1 Registers + */ +#define MBOX_IGU1_ISRS PPE_REG_ADDR(0x0204) +#define MBOX_IGU1_ISRC PPE_REG_ADDR(0x0205) +#define MBOX_IGU1_ISR PPE_REG_ADDR(0x0206) +#define MBOX_IGU1_IER PPE_REG_ADDR(0x0207) + +#define MBOX_IGU1_ISRS_SET(n) (1 << (n)) +#define MBOX_IGU1_ISRC_CLEAR(n) (1 << (n)) +#define MBOX_IGU1_ISR_ISR(n) (*MBOX_IGU1_ISR & (1 << (n))) +#define MBOX_IGU1_IER_EN(n) (*MBOX_IGU1_IER & (1 << (n))) +#define MBOX_IGU1_IER_EN_SET(n) (1 << (n)) + +/* + * Mailbox IGU3 Registers + */ +#define MBOX_IGU3_ISRS PPE_REG_ADDR(0x0214) +#define MBOX_IGU3_ISRC PPE_REG_ADDR(0x0215) +#define MBOX_IGU3_ISR PPE_REG_ADDR(0x0216) +#define MBOX_IGU3_IER PPE_REG_ADDR(0x0217) + +#define MBOX_IGU3_ISRS_SET(n) (1 << (n)) +#define MBOX_IGU3_ISRC_CLEAR(n) (1 << (n)) +#define MBOX_IGU3_ISR_ISR(n) (*MBOX_IGU3_ISR & (1 << (n))) +#define MBOX_IGU3_IER_EN(n) (*MBOX_IGU3_IER & (1 << (n))) +#define MBOX_IGU3_IER_EN_SET(n) (1 << (n)) + +/* + * RTHA/TTHA Registers + */ +#define RFBI_CFG PPE_REG_ADDR(0x0400) +#define RBA_CFG0 PPE_REG_ADDR(0x0404) +#define RBA_CFG1 PPE_REG_ADDR(0x0405) +#define RCA_CFG0 PPE_REG_ADDR(0x0408) +#define RCA_CFG1 PPE_REG_ADDR(0x0409) +#define RDES_CFG0 PPE_REG_ADDR(0x040C) +#define RDES_CFG1 PPE_REG_ADDR(0x040D) +#define SFSM_STATE0 PPE_REG_ADDR(0x0410) +#define SFSM_STATE1 PPE_REG_ADDR(0x0411) +#define SFSM_DBA0 PPE_REG_ADDR(0x0412) +#define SFSM_DBA1 PPE_REG_ADDR(0x0413) +#define SFSM_CBA0 PPE_REG_ADDR(0x0414) +#define SFSM_CBA1 PPE_REG_ADDR(0x0415) +#define SFSM_CFG0 PPE_REG_ADDR(0x0416) +#define SFSM_CFG1 PPE_REG_ADDR(0x0417) +#define SFSM_PGCNT0 PPE_REG_ADDR(0x041C) +#define SFSM_PGCNT1 PPE_REG_ADDR(0x041D) +#define FFSM_DBA0 PPE_REG_ADDR(0x0508) +#define FFSM_DBA1 PPE_REG_ADDR(0x0509) +#define FFSM_CFG0 PPE_REG_ADDR(0x050A) +#define FFSM_CFG1 PPE_REG_ADDR(0x050B) +#define FFSM_IDLE_HEAD_BC0 PPE_REG_ADDR(0x050E) +#define FFSM_IDLE_HEAD_BC1 PPE_REG_ADDR(0x050F) +#define FFSM_PGCNT0 PPE_REG_ADDR(0x0514) +#define FFSM_PGCNT1 PPE_REG_ADDR(0x0515) + +/* + * PPE TC Logic Registers (partial) + */ +#define DREG_A_VERSION PPE_REG_ADDR(0x0D00) +#define DREG_A_CFG PPE_REG_ADDR(0x0D01) +#define DREG_AT_CTRL PPE_REG_ADDR(0x0D02) +#define DREG_AT_CB_CFG0 PPE_REG_ADDR(0x0D03) +#define DREG_AT_CB_CFG1 PPE_REG_ADDR(0x0D04) +#define DREG_AR_CTRL PPE_REG_ADDR(0x0D08) +#define DREG_AR_CB_CFG0 PPE_REG_ADDR(0x0D09) +#define DREG_AR_CB_CFG1 PPE_REG_ADDR(0x0D0A) +#define DREG_A_UTPCFG PPE_REG_ADDR(0x0D0E) +#define DREG_A_STATUS PPE_REG_ADDR(0x0D0F) +#define DREG_AT_CFG0 PPE_REG_ADDR(0x0D20) +#define DREG_AT_CFG1 PPE_REG_ADDR(0x0D21) +#define DREG_AT_FB_SIZE0 PPE_REG_ADDR(0x0D22) +#define DREG_AT_FB_SIZE1 PPE_REG_ADDR(0x0D23) +#define DREG_AT_CELL0 PPE_REG_ADDR(0x0D24) +#define DREG_AT_CELL1 PPE_REG_ADDR(0x0D25) +#define DREG_AT_IDLE_CNT0 PPE_REG_ADDR(0x0D26) +#define DREG_AT_IDLE_CNT1 PPE_REG_ADDR(0x0D27) +#define DREG_AT_IDLE0 PPE_REG_ADDR(0x0D28) +#define DREG_AT_IDLE1 PPE_REG_ADDR(0x0D29) +#define DREG_AR_CFG0 PPE_REG_ADDR(0x0D60) +#define DREG_AR_CFG1 PPE_REG_ADDR(0x0D61) +#define DREG_AR_CELL0 PPE_REG_ADDR(0x0D68) +#define DREG_AR_CELL1 PPE_REG_ADDR(0x0D69) +#define DREG_AR_IDLE_CNT0 PPE_REG_ADDR(0x0D6A) +#define DREG_AR_IDLE_CNT1 PPE_REG_ADDR(0x0D6B) +#define DREG_AR_AIIDLE_CNT0 PPE_REG_ADDR(0x0D6C) +#define DREG_AR_AIIDLE_CNT1 PPE_REG_ADDR(0x0D6D) +#define DREG_AR_BE_CNT0 PPE_REG_ADDR(0x0D6E) +#define DREG_AR_BE_CNT1 PPE_REG_ADDR(0x0D6F) +#define DREG_AR_HEC_CNT0 PPE_REG_ADDR(0x0D70) +#define DREG_AR_HEC_CNT1 PPE_REG_ADDR(0x0D71) +#define DREG_AR_IDLE0 PPE_REG_ADDR(0x0D74) +#define DREG_AR_IDLE1 PPE_REG_ADDR(0x0D75) +#define DREG_AR_CVN_CNT0 PPE_REG_ADDR(0x0DA4) +#define DREG_AR_CVN_CNT1 PPE_REG_ADDR(0x0DA5) +#define DREG_AR_CVNP_CNT0 PPE_REG_ADDR(0x0DA6) +#define DREG_AR_CVNP_CNT1 PPE_REG_ADDR(0x0DA7) +#define DREG_B0_LADR PPE_REG_ADDR(0x0DA8) +#define DREG_B1_LADR PPE_REG_ADDR(0x0DA9) + +#define SFSM_DBA(i) ( (SFSM_dba * ) PPE_REG_ADDR(0x0412 + (i))) +#define SFSM_CBA(i) ( (SFSM_cba * ) PPE_REG_ADDR(0x0414 + (i))) +#define SFSM_CFG(i) ( (SFSM_cfg * ) PPE_REG_ADDR(0x0416 + (i))) +#define SFSM_PGCNT(i) ( (SFSM_pgcnt * ) PPE_REG_ADDR(0x041C + (i))) + +#define FFSM_DBA(i) ( (FFSM_dba * ) PPE_REG_ADDR(0x0508 + (i))) +#define FFSM_CFG(i) ( (FFSM_cfg * ) PPE_REG_ADDR(0x050A + (i))) +#define FFSM_PGCNT(i) ( (FFSM_pgcnt * ) PPE_REG_ADDR(0x0514 + (i))) + +typedef struct { + unsigned int res : 19; + unsigned int dbase : 13; +} SFSM_dba; + +typedef struct { + unsigned int res : 19; + unsigned int cbase : 13; +} SFSM_cba; + +typedef struct { + unsigned int res : 15; + unsigned int endian : 1; + unsigned int idlekeep: 1; + unsigned int sen : 1; + unsigned int res1 : 8; + unsigned int pnum : 6; +} SFSM_cfg; + +typedef struct { + unsigned int res : 17; + unsigned int pptr : 6; + unsigned int dcmd : 1; + unsigned int res1 : 2; + unsigned int upage : 6; +} SFSM_pgcnt; + +typedef struct { + unsigned int res : 19; + unsigned int dbase : 13; +} FFSM_dba; + +typedef struct { + unsigned int res : 12; + unsigned int rstptr : 1; + unsigned int clvpage : 1; + unsigned int fidle : 1; + unsigned int endian : 1; + unsigned int res1 : 10; + unsigned int pnum : 6; +} FFSM_cfg; + +typedef struct { + unsigned int res : 17; + unsigned int ival : 6; + unsigned int icmd : 1; + unsigned int res1 : 2; + unsigned int vpage : 6; +} FFSM_pgcnt; + + + +#endif // IFXMIPS_ATM_PPE_COMMON_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ppe_danube.h b/package/system/ltq-dsl/src/ifxmips_atm_ppe_danube.h new file mode 100644 index 0000000000..7e46cc1838 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ppe_danube.h @@ -0,0 +1,129 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_ppe_danube.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PPE Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_PPE_DANUBE_H +#define IFXMIPS_ATM_PPE_DANUBE_H + +#include <lantiq.h> + +/* + * FPI Configuration Bus Register and Memory Address Mapping + */ +#define IFX_PPE (KSEG1 | 0x1E180000) +#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0000) << 2))) +#define PPM_INT_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0030) << 2))) +#define PP32_INTERNAL_RES_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x0040) << 2))) +#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x1000) << 2))) +#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x4000) << 2))) +#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x5000) << 2))) +#define PPM_INT_UNIT_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6000) << 2))) +#define PPM_TIMER0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6100) << 2))) +#define PPM_TASK_IND_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6200) << 2))) +#define PPS_BRK_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6300) << 2))) +#define PPM_TIMER1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x6400) << 2))) +#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8000) << 2))) +#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8400) << 2))) +#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x8C00) << 2))) +#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x9600) << 2))) +#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0xC000) << 2))) + +/* + * DWORD-Length of Memory Blocks + */ +#define PP32_DEBUG_REG_DWLEN 0x0030 +#define PPM_INT_REG_DWLEN 0x0010 +#define PP32_INTERNAL_RES_DWLEN 0x00C0 +#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800) +#define PPE_REG_DWLEN 0x1000 +#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1) +#define PPM_INT_UNIT_DWLEN 0x0100 +#define PPM_TIMER0_DWLEN 0x0100 +#define PPM_TASK_IND_REG_DWLEN 0x0100 +#define PPS_BRK_DWLEN 0x0100 +#define PPM_TIMER1_DWLEN 0x0100 +#define SB_RAM0_DWLEN 0x0400 +#define SB_RAM1_DWLEN 0x0800 +#define SB_RAM2_DWLEN 0x0A00 +#define SB_RAM3_DWLEN 0x0400 +#define QSB_CONF_REG_DWLEN 0x0100 + +/* + * PP32 to FPI Address Mapping + */ +#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x23FF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \ + (((__sb_addr) >= 0x2400) && ((__sb_addr) <= 0x2BFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x2400) : \ + (((__sb_addr) >= 0x2C00) && ((__sb_addr) <= 0x35FF)) ? SB_RAM2_ADDR((__sb_addr) - 0x2C00) : \ + (((__sb_addr) >= 0x3600) && ((__sb_addr) <= 0x39FF)) ? SB_RAM3_ADDR((__sb_addr) - 0x3600) : \ + 0)) + +/* + * PP32 Debug Control Register + */ +#define PP32_DBG_CTRL PP32_DEBUG_REG_ADDR(0, 0x0000) + +#define DBG_CTRL_START_SET(value) ((value) ? (1 << 0) : 0) +#define DBG_CTRL_STOP_SET(value) ((value) ? (1 << 1) : 0) +#define DBG_CTRL_STEP_SET(value) ((value) ? (1 << 2) : 0) + +#define PP32_HALT_STAT PP32_DEBUG_REG_ADDR(0, 0x0001) + +#define PP32_BRK_SRC PP32_DEBUG_REG_ADDR(0, 0x0002) + +#define PP32_DBG_PC_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0010 + (i)) +#define PP32_DBG_PC_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x0014 + (i)) +#define PP32_DBG_DATA_MIN(i) PP32_DEBUG_REG_ADDR(0, 0x0018 + (i)) +#define PP32_DBG_DATA_MAX(i) PP32_DEBUG_REG_ADDR(0, 0x001A + (i)) +#define PP32_DBG_DATA_VAL(i) PP32_DEBUG_REG_ADDR(0, 0x001C + (i)) + +#define PP32_DBG_CUR_PC PP32_DEBUG_REG_ADDR(0, 0x0080) + +#define PP32_DBG_TASK_NO PP32_DEBUG_REG_ADDR(0, 0x0081) + +#define PP32_DBG_REG_BASE(tsk, i) PP32_DEBUG_REG_ADDR(0, 0x0100 + (tsk) * 16 + (i)) + +/* + * EMA Registers + */ +#define EMA_CMDCFG PPE_REG_ADDR(0x0A00) +#define EMA_DATACFG PPE_REG_ADDR(0x0A01) +#define EMA_CMDCNT PPE_REG_ADDR(0x0A02) +#define EMA_DATACNT PPE_REG_ADDR(0x0A03) +#define EMA_ISR PPE_REG_ADDR(0x0A04) +#define EMA_IER PPE_REG_ADDR(0x0A05) +#define EMA_CFG PPE_REG_ADDR(0x0A06) +#define EMA_SUBID PPE_REG_ADDR(0x0A07) + +#define EMA_ALIGNMENT 4 + +/* + * Mailbox IGU1 Interrupt + */ +#define PPE_MAILBOX_IGU1_INT LTQ_PPE_MBOX_INT + + + +#endif // IFXMIPS_ATM_PPE_DANUBE_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_ppe_vr9.h b/package/system/ltq-dsl/src/ifxmips_atm_ppe_vr9.h new file mode 100644 index 0000000000..316a772858 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_ppe_vr9.h @@ -0,0 +1,192 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_ppe_vr9.h +** PROJECT : UEIP +** MODULES : ATM (ADSL) +** +** DATE : 1 AUG 2005 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM Driver (PPE Registers) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 4 AUG 2005 Xu Liang Initiate Version +** 23 OCT 2006 Xu Liang Add GPL header. +** 9 JAN 2007 Xu Liang First version got from Anand (IC designer) +*******************************************************************************/ + + + +#ifndef IFXMIPS_ATM_PPE_VR9_H +#define IFXMIPS_ATM_PPE_VR9_H + + + +/* + * FPI Configuration Bus Register and Memory Address Mapping + */ +#define IFX_PPE (KSEG1 | 0x1E200000) +#define PP32_DEBUG_REG_ADDR(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x000000 + (i) * 0x00010000) << 2))) +#define CDM_CODE_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x001000 + (i) * 0x00010000) << 2))) +#define CDM_DATA_MEMORY(i, x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x004000 + (i) * 0x00010000) << 2))) +#define SB_RAM0_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x008000) << 2))) +#define SB_RAM1_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x009000) << 2))) +#define SB_RAM2_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00A000) << 2))) +#define SB_RAM3_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00B000) << 2))) +#define PPE_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00D000) << 2))) +#define QSB_CONF_REG_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x00E000) << 2))) +#define SB_RAM6_ADDR(x) ((volatile unsigned int*)(IFX_PPE + (((x) + 0x018000) << 2))) + +/* + * DWORD-Length of Memory Blocks + */ +#define PP32_DEBUG_REG_DWLEN 0x0030 +#define CDM_CODE_MEMORYn_DWLEN(n) ((n) == 0 ? 0x1000 : 0x0800) +#define CDM_DATA_MEMORY_DWLEN CDM_CODE_MEMORYn_DWLEN(1) +#define SB_RAM0_DWLEN 0x1000 +#define SB_RAM1_DWLEN 0x1000 +#define SB_RAM2_DWLEN 0x1000 +#define SB_RAM3_DWLEN 0x1000 +#define SB_RAM6_DWLEN 0x8000 +#define QSB_CONF_REG_DWLEN 0x0100 + +/* + * PP32 to FPI Address Mapping + */ +#define SB_BUFFER(__sb_addr) ((volatile unsigned int *)((((__sb_addr) >= 0x0000) && ((__sb_addr) <= 0x1FFF)) ? PPE_REG_ADDR((__sb_addr)) : \ + (((__sb_addr) >= 0x2000) && ((__sb_addr) <= 0x2FFF)) ? SB_RAM0_ADDR((__sb_addr) - 0x2000) : \ + (((__sb_addr) >= 0x3000) && ((__sb_addr) <= 0x3FFF)) ? SB_RAM1_ADDR((__sb_addr) - 0x3000) : \ + (((__sb_addr) >= 0x4000) && ((__sb_addr) <= 0x4FFF)) ? SB_RAM2_ADDR((__sb_addr) - 0x4000) : \ + (((__sb_addr) >= 0x5000) && ((__sb_addr) <= 0x5FFF)) ? SB_RAM3_ADDR((__sb_addr) - 0x5000) : \ + (((__sb_addr) >= 0x7000) && ((__sb_addr) <= 0x7FFF)) ? PPE_REG_ADDR((__sb_addr) - 0x7000) : \ + (((__sb_addr) >= 0x8000) && ((__sb_addr) <= 0xFFFF)) ? SB_RAM6_ADDR((__sb_addr) - 0x8000) : \ + 0)) + +/* + * PP32 Debug Control Register + */ +#define NUM_OF_PP32 2 + +#define PP32_FREEZE PPE_REG_ADDR(0x0000) +#define PP32_SRST PPE_REG_ADDR(0x0020) + +#define PP32_DBG_CTRL(n) PP32_DEBUG_REG_ADDR(n, 0x0000) + +#define DBG_CTRL_RESTART 0 +#define DBG_CTRL_STOP 1 + +#define PP32_CTRL_CMD(n) PP32_DEBUG_REG_ADDR(n, 0x0B00) + #define PP32_CTRL_CMD_RESTART (1 << 0) + #define PP32_CTRL_CMD_STOP (1 << 1) + #define PP32_CTRL_CMD_STEP (1 << 2) + #define PP32_CTRL_CMD_BREAKOUT (1 << 3) + +#define PP32_CTRL_OPT(n) PP32_DEBUG_REG_ADDR(n, 0x0C00) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_ON (3 << 0) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP_OFF (2 << 0) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_ON (3 << 2) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN_OFF (2 << 2) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN_ON (3 << 4) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN_OFF (2 << 4) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_ON (3 << 6) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT_OFF (2 << 6) + #define PP32_CTRL_OPT_BREAKOUT_ON_STOP(n) (*PP32_CTRL_OPT(n) & (1 << 0)) + #define PP32_CTRL_OPT_BREAKOUT_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 2)) + #define PP32_CTRL_OPT_STOP_ON_BREAKIN(n) (*PP32_CTRL_OPT(n) & (1 << 4)) + #define PP32_CTRL_OPT_STOP_ON_BREAKPOINT(n) (*PP32_CTRL_OPT(n) & (1 << 6)) + +#define PP32_BRK_PC(n, i) PP32_DEBUG_REG_ADDR(n, 0x0900 + (i) * 2) +#define PP32_BRK_PC_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0901 + (i) * 2) +#define PP32_BRK_DATA_ADDR(n, i) PP32_DEBUG_REG_ADDR(n, 0x0904 + (i) * 2) +#define PP32_BRK_DATA_ADDR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0905 + (i) * 2) +#define PP32_BRK_DATA_VALUE_RD(n, i) PP32_DEBUG_REG_ADDR(n, 0x0908 + (i) * 2) +#define PP32_BRK_DATA_VALUE_RD_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x0909 + (i) * 2) +#define PP32_BRK_DATA_VALUE_WR(n, i) PP32_DEBUG_REG_ADDR(n, 0x090C + (i) * 2) +#define PP32_BRK_DATA_VALUE_WR_MASK(n, i) PP32_DEBUG_REG_ADDR(n, 0x090D + (i) * 2) + #define PP32_BRK_CONTEXT_MASK(i) (1 << (i)) + #define PP32_BRK_CONTEXT_MASK_EN (1 << 4) + #define PP32_BRK_COMPARE_GREATER_EQUAL (1 << 5) // valid for break data value rd/wr only + #define PP32_BRK_COMPARE_LOWER_EQUAL (1 << 6) + #define PP32_BRK_COMPARE_EN (1 << 7) + +#define PP32_BRK_TRIG(n) PP32_DEBUG_REG_ADDR(n, 0x0F00) + #define PP32_BRK_GRPi_PCn_ON(i, n) ((3 << ((n) * 2)) << ((i) * 16)) + #define PP32_BRK_GRPi_PCn_OFF(i, n) ((2 << ((n) * 2)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_ADDRn_ON(i, n) ((3 << ((n) * 2 + 4)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_ADDRn_OFF(i, n) ((2 << ((n) * 2 + 4)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_RDn_ON(i, n) ((3 << ((n) * 2 + 8)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_RDn_OFF(i, n)((2 << ((n) * 2 + 8)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_WRn_ON(i, n) ((3 << ((n) * 2 + 12)) << ((i) * 16)) + #define PP32_BRK_GRPi_DATA_VALUE_WRn_OFF(i, n)((2 << ((n) * 2 + 12)) << ((i) * 16)) + #define PP32_BRK_GRPi_PCn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n))) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_ADDRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 2)) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_VALUE_RDn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 4)) << ((i) * 8))) + #define PP32_BRK_GRPi_DATA_VALUE_WRn(k, i, n) (*PP32_BRK_TRIG(k) & ((1 << ((n) + 6)) << ((i) * 8))) + +#define PP32_CPU_STATUS(n) PP32_DEBUG_REG_ADDR(n, 0x0D00) +#define PP32_HALT_STAT(n) PP32_CPU_STATUS(n) +#define PP32_DBG_CUR_PC(n) PP32_CPU_STATUS(n) + #define PP32_CPU_USER_STOPPED(n) (*PP32_CPU_STATUS(n) & (1 << 0)) + #define PP32_CPU_USER_BREAKIN_RCV(n) (*PP32_CPU_STATUS(n) & (1 << 1)) + #define PP32_CPU_USER_BREAKPOINT_MET(n) (*PP32_CPU_STATUS(n) & (1 << 2)) + #define PP32_CPU_CUR_PC(n) (*PP32_CPU_STATUS(n) >> 16) + +#define PP32_BREAKPOINT_REASONS(n) PP32_DEBUG_REG_ADDR(n, 0x0A00) + #define PP32_BRK_PC_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << (i))) + #define PP32_BRK_DATA_ADDR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 2))) + #define PP32_BRK_DATA_VALUE_RD_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 4))) + #define PP32_BRK_DATA_VALUE_WR_MET(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) + 6))) + #define PP32_BRK_DATA_VALUE_RD_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 8))) + #define PP32_BRK_DATA_VALUE_RD_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 9))) + #define PP32_BRK_DATA_VALUE_WR_LO_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 12))) + #define PP32_BRK_DATA_VALUE_WR_GT_EQ(n, i) (*PP32_BREAKPOINT_REASONS(n) & (1 << ((i) * 2 + 13))) + #define PP32_BRK_CUR_CONTEXT(n) ((*PP32_BREAKPOINT_REASONS(n) >> 16) & 0x03) + +#define PP32_GP_REG_BASE(n) PP32_DEBUG_REG_ADDR(n, 0x0E00) +#define PP32_GP_CONTEXTi_REGn(n, i, j) PP32_DEBUG_REG_ADDR(n, 0x0E00 + (i) * 16 + (j)) + +/* + * PDMA/EMA Registers + */ +#define PDMA_CFG PPE_REG_ADDR(0x0A00) +#define PDMA_RX_CMDCNT PPE_REG_ADDR(0x0A01) +#define PDMA_TX_CMDCNT PPE_REG_ADDR(0x0A02) +#define PDMA_RX_FWDATACNT PPE_REG_ADDR(0x0A03) +#define PDMA_TX_FWDATACNT PPE_REG_ADDR(0x0A04) +#define PDMA_RX_CTX_CFG PPE_REG_ADDR(0x0A05) +#define PDMA_TX_CTX_CFG PPE_REG_ADDR(0x0A06) +#define PDMA_RX_MAX_LEN_REG PPE_REG_ADDR(0x0A07) +#define PDMA_RX_DELAY_CFG PPE_REG_ADDR(0x0A08) +#define PDMA_INT_FIFO_RD PPE_REG_ADDR(0x0A09) +#define PDMA_ISR PPE_REG_ADDR(0x0A0A) +#define PDMA_IER PPE_REG_ADDR(0x0A0B) +#define PDMA_SUBID PPE_REG_ADDR(0x0A0C) +#define PDMA_BAR0 PPE_REG_ADDR(0x0A0D) +#define PDMA_BAR1 PPE_REG_ADDR(0x0A0E) + +#define SAR_PDMA_RX_CMDBUF_CFG PPE_REG_ADDR(0x0F00) +#define SAR_PDMA_TX_CMDBUF_CFG PPE_REG_ADDR(0x0F01) +#define SAR_PDMA_RX_FW_CMDBUF_CFG PPE_REG_ADDR(0x0F02) +#define SAR_PDMA_TX_FW_CMDBUF_CFG PPE_REG_ADDR(0x0F03) +#define SAR_PDMA_RX_CMDBUF_STATUS PPE_REG_ADDR(0x0F04) +#define SAR_PDMA_TX_CMDBUF_STATUS PPE_REG_ADDR(0x0F05) + +#define PDMA_ALIGNMENT 4 +#define EMA_ALIGNMENT PDMA_ALIGNMENT + +/* + * Mailbox IGU1 Interrupt + */ +#define PPE_MAILBOX_IGU1_INT INT_NUM_IM2_IRL0 + 24 + + + +#endif // IFXMIPS_ATM_PPE_VR9_H diff --git a/package/system/ltq-dsl/src/ifxmips_atm_vr9.c b/package/system/ltq-dsl/src/ifxmips_atm_vr9.c new file mode 100644 index 0000000000..ea84c4c83f --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_atm_vr9.c @@ -0,0 +1,303 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_atm_vr9.c +** PROJECT : UEIP +** MODULES : ATM +** +** DATE : 7 Jul 2009 +** AUTHOR : Xu Liang +** DESCRIPTION : ATM driver common source file (core functions) +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** HISTORY +** $Date $Author $Comment +** 07 JUL 2009 Xu Liang Init Version +*******************************************************************************/ + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <asm/delay.h> + +/* + * Chip Specific Head File + */ +#include <ifx_types.h> +#include <ifx_regs.h> +#include <common_routines.h> +#include <ifx_pmu.h> +#include <ifx_rcu.h> +#include "ifxmips_atm_core.h" +#include "ifxmips_atm_fw_vr9.h" + + + +/* + * #################################### + * Definition + * #################################### + */ + + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Hardware Init/Uninit Functions + */ +static inline void init_pmu(void); +static inline void uninit_pmu(void); +static inline void reset_ppe(void); +static inline void init_pdma(void); +static inline void init_mailbox(void); +static inline void init_atm_tc(void); +static inline void clear_share_buffer(void); + + + +/* + * #################################### + * Local Variable + * #################################### + */ + + + +/* + * #################################### + * Local Function + * #################################### + */ + +static inline void init_pmu(void) +{ + //*PMU_PWDCR &= ~((1 << 29) | (1 << 22) | (1 << 21) | (1 << 19) | (1 << 18)); + //PPE_TOP_PMU_SETUP(IFX_PMU_ENABLE); + PPE_SLL01_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TC_PMU_SETUP(IFX_PMU_ENABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_ENABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_ENABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_ENABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_ENABLE); +} + +static inline void uninit_pmu(void) +{ + PPE_SLL01_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TC_PMU_SETUP(IFX_PMU_DISABLE); + PPE_EMA_PMU_SETUP(IFX_PMU_DISABLE); + PPE_QSB_PMU_SETUP(IFX_PMU_DISABLE); + PPE_TPE_PMU_SETUP(IFX_PMU_DISABLE); + DSL_DFE_PMU_SETUP(IFX_PMU_DISABLE); + //PPE_TOP_PMU_SETUP(IFX_PMU_DISABLE); +} + +static inline void reset_ppe(void) +{ +#ifdef MODULE + // reset PPE + ifx_rcu_rst(IFX_RCU_DOMAIN_DSLDFE, IFX_RCU_MODULE_ATM); + udelay(1000); + ifx_rcu_rst(IFX_RCU_DOMAIN_DSLTC, IFX_RCU_MODULE_ATM); + udelay(1000); + ifx_rcu_rst(IFX_RCU_DOMAIN_PPE, IFX_RCU_MODULE_ATM); + udelay(1000); + *PP32_SRST &= ~0x000303CF; + udelay(1000); + *PP32_SRST |= 0x000303CF; + udelay(1000); +#endif +} + +static inline void init_pdma(void) +{ + IFX_REG_W32(0x08, PDMA_CFG); + IFX_REG_W32(0x00203580, SAR_PDMA_RX_CMDBUF_CFG); + IFX_REG_W32(0x004035A0, SAR_PDMA_RX_FW_CMDBUF_CFG); +} + +static inline void init_mailbox(void) +{ + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU1_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU1_IER); + IFX_REG_W32(0xFFFFFFFF, MBOX_IGU3_ISRC); + IFX_REG_W32(0x00000000, MBOX_IGU3_IER); +} + +static inline void init_atm_tc(void) +{ + /* clear sync state */ + *SFSM_STATE0 = 0; + *SFSM_STATE1 = 0; + + /* enable keep IDLE */ +// *SFSM_CFG0 |= 1 << 15; +// *SFSM_CFG1 |= 1 << 15; +} + +static inline void clear_share_buffer(void) +{ + volatile u32 *p; + unsigned int i; + + p = SB_RAM0_ADDR(0); + for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ ) + IFX_REG_W32(0, p++); + + p = SB_RAM6_ADDR(0); + for ( i = 0; i < SB_RAM6_DWLEN; i++ ) + IFX_REG_W32(0, p++); +} + +/* + * Description: + * Download PPE firmware binary code. + * Input: + * pp32 --- int, which pp32 core + * src --- u32 *, binary code buffer + * dword_len --- unsigned int, binary code length in DWORD (32-bit) + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +static inline int pp32_download_code(int pp32, u32 *code_src, unsigned int code_dword_len, u32 *data_src, unsigned int data_dword_len) +{ + unsigned int clr, set; + volatile u32 *dest; + + if ( code_src == 0 || ((unsigned long)code_src & 0x03) != 0 + || data_src == 0 || ((unsigned long)data_src & 0x03) != 0 ) + return IFX_ERROR; + + clr = pp32 ? 0xF0 : 0x0F; + if ( code_dword_len <= CDM_CODE_MEMORYn_DWLEN(0) ) + set = pp32 ? (3 << 6): (2 << 2); + else + set = 0x00; + IFX_REG_W32_MASK(clr, set, CDM_CFG); + + /* copy code */ + dest = CDM_CODE_MEMORY(pp32, 0); + while ( code_dword_len-- > 0 ) + IFX_REG_W32(*code_src++, dest++); + + /* copy data */ + dest = CDM_DATA_MEMORY(pp32, 0); + while ( data_dword_len-- > 0 ) + IFX_REG_W32(*data_src++, dest++); + + return IFX_SUCCESS; +} + + + +/* + * #################################### + * Global Function + * #################################### + */ + +extern void ifx_atm_get_fw_ver(unsigned int *major, unsigned int *minor) +{ + ASSERT(major != NULL, "pointer is NULL"); + ASSERT(minor != NULL, "pointer is NULL"); + +#ifdef VER_IN_FIRMWARE + *major = FW_VER_ID->major; + *minor = FW_VER_ID->minor; +#else + *major = ATM_FW_VER_MAJOR; + *minor = ATM_FW_VER_MINOR; +#endif +} + +void ifx_atm_init_chip(void) +{ + init_pmu(); + + reset_ppe(); + + init_pdma(); + + init_mailbox(); + + init_atm_tc(); + + clear_share_buffer(); +} + +void ifx_atm_uninit_chip(void) +{ + uninit_pmu(); +} + +/* + * Description: + * Initialize and start up PP32. + * Input: + * none + * Output: + * int --- IFX_SUCCESS: Success + * else: Error Code + */ +int ifx_pp32_start(int pp32) +{ + unsigned int mask = 1 << (pp32 << 4); + int ret; + + /* download firmware */ + ret = pp32_download_code(pp32, firmware_binary_code, sizeof(firmware_binary_code) / sizeof(*firmware_binary_code), firmware_binary_data, sizeof(firmware_binary_data) / sizeof(*firmware_binary_data)); + if ( ret != IFX_SUCCESS ) + return ret; + + /* run PP32 */ + IFX_REG_W32_MASK(mask, 0, PP32_FREEZE); + + /* idle for a while to let PP32 init itself */ + udelay(10); + + return IFX_SUCCESS; +} + +/* + * Description: + * Halt PP32. + * Input: + * none + * Output: + * none + */ +void ifx_pp32_stop(int pp32) +{ + unsigned int mask = 1 << (pp32 << 4); + + /* halt PP32 */ + IFX_REG_W32_MASK(0, mask, PP32_FREEZE); +} diff --git a/package/system/ltq-dsl/src/ifxmips_compat.h b/package/system/ltq-dsl/src/ifxmips_compat.h new file mode 100644 index 0000000000..b0c9f25f48 --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_compat.h @@ -0,0 +1,56 @@ +#ifndef _IFXMIPS_COMPAT_H__ +#define _IFXMIPS_COMPAT_H__ + +#define IFX_SUCCESS 0 +#define IFX_ERROR (-1) + +#define ATM_VBR_NRT ATM_VBR +#define ATM_VBR_RT 6 +#define ATM_UBR_PLUS 7 +#define ATM_GFR 8 + +#define NUM_ENTITY(x) (sizeof(x) / sizeof(*(x))) + +#define SET_BITS(x, msb, lsb, value) \ + (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb))) + + +#define IFX_PP32_ETOP_CFG 0x16020 +#define IFX_PP32_ETOP_MDIO_CFG 0x11804 +#define IFX_PP32_ETOP_IG_PLEN_CTRL 0x16080 +#define IFX_PP32_ENET_MAC_CFG 0x1840 + +#define IFX_RCU_DOMAIN_PPE (1 << 8) +#define IFX_RCU_MODULE_ATM + +#define IFX_PMU_ENABLE 1 +#define IFX_PMU_DISABLE 0 + +#define IFX_PMU_MODULE_DSL_DFE (1 << 9) +#define IFX_PMU_MODULE_AHBS (1 << 13) +#define IFX_PMU_MODULE_PPE_QSB (1 << 18) +#define IFX_PMU_MODULE_PPE_SLL01 (1 << 19) +#define IFX_PMU_MODULE_PPE_TC (1 << 21) +#define IFX_PMU_MODULE_PPE_EMA (1 << 22) +#define IFX_PMU_MODULE_PPE_TOP (1 << 29) + +extern void ltq_pmu_enable(unsigned int module); +extern void ltq_pmu_disable(unsigned int module); + +#define ifx_pmu_set(a,b) {if(a == IFX_PMU_ENABLE) ltq_pmu_enable(b); else ltq_pmu_disable(b);} + +#define PPE_TOP_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TOP, (__x)) +#define PPE_SLL01_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_SLL01, (__x)) +#define PPE_TC_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TC, (__x)) +#define PPE_EMA_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_EMA, (__x)) +#define PPE_QSB_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_QSB, (__x)) +#define PPE_TPE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_AHBS, (__x)) +#define DSL_DFE_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_DSL_DFE, (__x)) + +#define IFX_REG_W32(_v, _r) __raw_writel((_v), (_r)) + +#define CONFIG_IFXMIPS_DSL_CPE_MEI y + +#define INT_NUM_IM2_IRL24 (INT_NUM_IM2_IRL0 + 24) + +#endif diff --git a/package/system/ltq-dsl/src/ifxmips_mei_interface.h b/package/system/ltq-dsl/src/ifxmips_mei_interface.h new file mode 100644 index 0000000000..4ddc4c6aed --- /dev/null +++ b/package/system/ltq-dsl/src/ifxmips_mei_interface.h @@ -0,0 +1,702 @@ +/****************************************************************************** + + Copyright (c) 2009 + Infineon Technologies AG + Am Campeon 1-12; 81726 Munich, Germany + + For licensing information, see the file 'LICENSE' in the root folder of + this software module. + +******************************************************************************/ + +#ifndef IFXMIPS_MEI_H +#define IFXMIPS_MEI_H + +//#define CONFIG_AMAZON_SE 1 +//#define CONFIG_DANUBE 1 +//#define CONFIG_AR9 1 + +#if !defined(CONFIG_DANUBE) && !defined(CONFIG_AMAZON_SE) && !defined(CONFIG_AR9) && !defined(CONFIG_VR9) +#error Platform undefined!!! +#endif + +#ifdef IFX_MEI_BSP +/** This is the character datatype. */ +typedef char DSL_char_t; +/** This is the unsigned 8-bit datatype. */ +typedef unsigned char DSL_uint8_t; +/** This is the signed 8-bit datatype. */ +typedef signed char DSL_int8_t; +/** This is the unsigned 16-bit datatype. */ +typedef unsigned short DSL_uint16_t; +/** This is the signed 16-bit datatype. */ +typedef signed short DSL_int16_t; +/** This is the unsigned 32-bit datatype. */ +typedef unsigned long DSL_uint32_t; +/** This is the signed 32-bit datatype. */ +typedef signed long DSL_int32_t; +/** This is the float datatype. */ +typedef float DSL_float_t; +/** This is the void datatype. */ +typedef void DSL_void_t; +/** integer type, width is depending on processor arch */ +typedef int DSL_int_t; +/** unsigned integer type, width is depending on processor arch */ +typedef unsigned int DSL_uint_t; +typedef struct file DSL_DRV_file_t; +typedef struct inode DSL_DRV_inode_t; + +/** + * Defines all possible CMV groups + * */ +typedef enum { + DSL_CMV_GROUP_CNTL = 1, + DSL_CMV_GROUP_STAT = 2, + DSL_CMV_GROUP_INFO = 3, + DSL_CMV_GROUP_TEST = 4, + DSL_CMV_GROUP_OPTN = 5, + DSL_CMV_GROUP_RATE = 6, + DSL_CMV_GROUP_PLAM = 7, + DSL_CMV_GROUP_CNFG = 8 +} DSL_CmvGroup_t; +/** + * Defines all opcode types + * */ +typedef enum { + H2D_CMV_READ = 0x00, + H2D_CMV_WRITE = 0x04, + H2D_CMV_INDICATE_REPLY = 0x10, + H2D_ERROR_OPCODE_UNKNOWN =0x20, + H2D_ERROR_CMV_UNKNOWN =0x30, + + D2H_CMV_READ_REPLY =0x01, + D2H_CMV_WRITE_REPLY = 0x05, + D2H_CMV_INDICATE = 0x11, + D2H_ERROR_OPCODE_UNKNOWN = 0x21, + D2H_ERROR_CMV_UNKNOWN = 0x31, + D2H_ERROR_CMV_READ_NOT_AVAILABLE = 0x41, + D2H_ERROR_CMV_WRITE_ONLY = 0x51, + D2H_ERROR_CMV_READ_ONLY = 0x61, + + H2D_DEBUG_READ_DM = 0x02, + H2D_DEBUG_READ_PM = 0x06, + H2D_DEBUG_WRITE_DM = 0x0a, + H2D_DEBUG_WRITE_PM = 0x0e, + + D2H_DEBUG_READ_DM_REPLY = 0x03, + D2H_DEBUG_READ_FM_REPLY = 0x07, + D2H_DEBUG_WRITE_DM_REPLY = 0x0b, + D2H_DEBUG_WRITE_FM_REPLY = 0x0f, + D2H_ERROR_ADDR_UNKNOWN = 0x33, + + D2H_AUTONOMOUS_MODEM_READY_MSG = 0xf1 +} DSL_CmvOpcode_t; + +/* mutex macros */ +#define MEI_MUTEX_INIT(id,flag) \ + sema_init(&id,flag) +#define MEI_MUTEX_LOCK(id) \ + down_interruptible(&id) +#define MEI_MUTEX_UNLOCK(id) \ + up(&id) +#define MEI_WAIT(ms) \ + {\ + set_current_state(TASK_INTERRUPTIBLE);\ + schedule_timeout(ms);\ + } +#define MEI_INIT_WAKELIST(name,queue) \ + init_waitqueue_head(&queue) + +/* wait for an event, timeout is measured in ms */ +#define MEI_WAIT_EVENT_TIMEOUT(ev,timeout)\ + interruptible_sleep_on_timeout(&ev,timeout * HZ / 1000) +#define MEI_WAKEUP_EVENT(ev)\ + wake_up_interruptible(&ev) +#endif /* IFX_MEI_BSP */ + +/*** Register address offsets, relative to MEI_SPACE_ADDRESS ***/ +#define ME_DX_DATA (0x0000) +#define ME_VERSION (0x0004) +#define ME_ARC_GP_STAT (0x0008) +#define ME_DX_STAT (0x000C) +#define ME_DX_AD (0x0010) +#define ME_DX_MWS (0x0014) +#define ME_ME2ARC_INT (0x0018) +#define ME_ARC2ME_STAT (0x001C) +#define ME_ARC2ME_MASK (0x0020) +#define ME_DBG_WR_AD (0x0024) +#define ME_DBG_RD_AD (0x0028) +#define ME_DBG_DATA (0x002C) +#define ME_DBG_DECODE (0x0030) +#define ME_CONFIG (0x0034) +#define ME_RST_CTRL (0x0038) +#define ME_DBG_MASTER (0x003C) +#define ME_CLK_CTRL (0x0040) +#define ME_BIST_CTRL (0x0044) +#define ME_BIST_STAT (0x0048) +#define ME_XDATA_BASE_SH (0x004c) +#define ME_XDATA_BASE (0x0050) +#define ME_XMEM_BAR_BASE (0x0054) +#define ME_XMEM_BAR0 (0x0054) +#define ME_XMEM_BAR1 (0x0058) +#define ME_XMEM_BAR2 (0x005C) +#define ME_XMEM_BAR3 (0x0060) +#define ME_XMEM_BAR4 (0x0064) +#define ME_XMEM_BAR5 (0x0068) +#define ME_XMEM_BAR6 (0x006C) +#define ME_XMEM_BAR7 (0x0070) +#define ME_XMEM_BAR8 (0x0074) +#define ME_XMEM_BAR9 (0x0078) +#define ME_XMEM_BAR10 (0x007C) +#define ME_XMEM_BAR11 (0x0080) +#define ME_XMEM_BAR12 (0x0084) +#define ME_XMEM_BAR13 (0x0088) +#define ME_XMEM_BAR14 (0x008C) +#define ME_XMEM_BAR15 (0x0090) +#define ME_XMEM_BAR16 (0x0094) + +#define WHILE_DELAY 20000 +/* +** Define where in ME Processor's memory map the Stratify chip lives +*/ + +#define MAXSWAPSIZE (8 * 1024) //8k *(32bits) + +// Mailboxes +#define MSG_LENGTH 16 // x16 bits +#define YES_REPLY 1 +#define NO_REPLY 0 + +#define CMV_TIMEOUT 1000 //jiffies + +// Block size per BAR +#define SDRAM_SEGMENT_SIZE (64*1024) +// Number of Bar registers +#define MAX_BAR_REGISTERS (17) + +#define XDATA_REGISTER (15) + +// ARC register addresss +#define ARC_STATUS 0x0 +#define ARC_LP_START 0x2 +#define ARC_LP_END 0x3 +#define ARC_DEBUG 0x5 +#define ARC_INT_MASK 0x10A + +#define IRAM0_BASE (0x00000) +#define IRAM1_BASE (0x04000) +#if defined(CONFIG_DANUBE) +#define BRAM_BASE (0x0A000) +#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9) +#define BRAM_BASE (0x08000) +#endif +#define XRAM_BASE (0x18000) +#define YRAM_BASE (0x1A000) +#define EXT_MEM_BASE (0x80000) +#define ARC_GPIO_CTRL (0xC030) +#define ARC_GPIO_DATA (0xC034) + +#define IRAM0_SIZE (16*1024) +#define IRAM1_SIZE (16*1024) +#define BRAM_SIZE (12*1024) +#define XRAM_SIZE (8*1024) +#define YRAM_SIZE (8*1024) +#define EXT_MEM_SIZE (1536*1024) + +#define ADSL_BASE (0x20000) +#define CRI_BASE (ADSL_BASE + 0x11F00) +#define CRI_CCR0 (CRI_BASE + 0x00) +#define CRI_RST (CRI_BASE + 0x04*4) +#define ADSL_DILV_BASE (ADSL_BASE+0x20000) + +// +#define IRAM0_ADDR_BIT_MASK 0xFFF +#define IRAM1_ADDR_BIT_MASK 0xFFF +#define BRAM_ADDR_BIT_MASK 0xFFF +#define RX_DILV_ADDR_BIT_MASK 0x1FFF + +/*** Bit definitions ***/ +#define ARC_AUX_HALT (1 << 25) +#define ARC_DEBUG_HALT (1 << 1) +#define FALSE 0 +#define TRUE 1 +#define BIT0 (1<<0) +#define BIT1 (1<<1) +#define BIT2 (1<<2) +#define BIT3 (1<<3) +#define BIT4 (1<<4) +#define BIT5 (1<<5) +#define BIT6 (1<<6) +#define BIT7 (1<<7) +#define BIT8 (1<<8) +#define BIT9 (1<<9) +#define BIT10 (1<<10) +#define BIT11 (1<<11) +#define BIT12 (1<<12) +#define BIT13 (1<<13) +#define BIT14 (1<<14) +#define BIT15 (1<<15) +#define BIT16 (1<<16) +#define BIT17 (1<<17) +#define BIT18 (1<<18) +#define BIT19 (1<<19) +#define BIT20 (1<<20) +#define BIT21 (1<<21) +#define BIT22 (1<<22) +#define BIT23 (1<<23) +#define BIT24 (1<<24) +#define BIT25 (1<<25) +#define BIT26 (1<<26) +#define BIT27 (1<<27) +#define BIT28 (1<<28) +#define BIT29 (1<<29) +#define BIT30 (1<<30) +#define BIT31 (1<<31) + +// CRI_CCR0 Register definitions +#define CLK_2M_MODE_ENABLE BIT6 +#define ACL_CLK_MODE_ENABLE BIT4 +#define FDF_CLK_MODE_ENABLE BIT2 +#define STM_CLK_MODE_ENABLE BIT0 + +// CRI_RST Register definitions +#define FDF_SRST BIT3 +#define MTE_SRST BIT2 +#define FCI_SRST BIT1 +#define AAI_SRST BIT0 + +// MEI_TO_ARC_INTERRUPT Register definitions +#define MEI_TO_ARC_INT1 BIT3 +#define MEI_TO_ARC_INT0 BIT2 +#define MEI_TO_ARC_CS_DONE BIT1 //need to check +#define MEI_TO_ARC_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT Register definitions +#define ARC_TO_MEI_INT1 BIT8 +#define ARC_TO_MEI_INT0 BIT7 +#define ARC_TO_MEI_CS_REQ BIT6 +#define ARC_TO_MEI_DBG_DONE BIT5 +#define ARC_TO_MEI_MSGACK BIT4 +#define ARC_TO_MEI_NO_ACCESS BIT3 +#define ARC_TO_MEI_CHECK_AAITX BIT2 +#define ARC_TO_MEI_CHECK_AAIRX BIT1 +#define ARC_TO_MEI_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT_MASK Register definitions +#define GP_INT1_EN BIT8 +#define GP_INT0_EN BIT7 +#define CS_REQ_EN BIT6 +#define DBG_DONE_EN BIT5 +#define MSGACK_EN BIT4 +#define NO_ACC_EN BIT3 +#define AAITX_EN BIT2 +#define AAIRX_EN BIT1 +#define MSGAV_EN BIT0 + +#define MEI_SOFT_RESET BIT0 + +#define HOST_MSTR BIT0 + +#define JTAG_MASTER_MODE 0x0 +#define MEI_MASTER_MODE HOST_MSTR + +// MEI_DEBUG_DECODE Register definitions +#define MEI_DEBUG_DEC_MASK (0x3) +#define MEI_DEBUG_DEC_AUX_MASK (0x0) +#define ME_DBG_DECODE_DMP1_MASK (0x1) +#define MEI_DEBUG_DEC_DMP2_MASK (0x2) +#define MEI_DEBUG_DEC_CORE_MASK (0x3) + +#define AUX_STATUS (0x0) +#define AUX_ARC_GPIO_CTRL (0x10C) +#define AUX_ARC_GPIO_DATA (0x10D) +// ARC_TO_MEI_MAILBOX[11] is a special location used to indicate +// page swap requests. +#if defined(CONFIG_DANUBE) +#define OMBOX_BASE 0xDF80 +#define ARC_TO_MEI_MAILBOX 0xDFA0 +#define IMBOX_BASE 0xDFC0 +#define MEI_TO_ARC_MAILBOX 0xDFD0 +#elif defined(CONFIG_AMAZON_SE) || defined(CONFIG_AR9) || defined(CONFIG_VR9) +#define OMBOX_BASE 0xAF80 +#define ARC_TO_MEI_MAILBOX 0xAFA0 +#define IMBOX_BASE 0xAFC0 +#define MEI_TO_ARC_MAILBOX 0xAFD0 +#endif + +#define MEI_TO_ARC_MAILBOXR (MEI_TO_ARC_MAILBOX + 0x2C) +#define ARC_MEI_MAILBOXR (ARC_TO_MEI_MAILBOX + 0x2C) +#define OMBOX1 (OMBOX_BASE+0x4) + +// Codeswap request messages are indicated by setting BIT31 +#define OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK (0x80000000) + +// Clear Eoc messages received are indicated by setting BIT17 +#define OMB_CLEAREOC_INTERRUPT_CODE (0x00020000) +#define OMB_REBOOT_INTERRUPT_CODE (1 << 18) + +/* +** Swap page header +*/ +// Page must be loaded at boot time if size field has BIT31 set +#define BOOT_FLAG (BIT31) +#define BOOT_FLAG_MASK ~BOOT_FLAG + +#define FREE_RELOAD 1 +#define FREE_SHOWTIME 2 +#define FREE_ALL 3 + +// marcos +#define IFX_MEI_WRITE_REGISTER_L(data,addr) *((volatile u32*)(addr)) = (u32)(data) +#define IFX_MEI_READ_REGISTER_L(addr) (*((volatile u32*)(addr))) +#define SET_BIT(reg, mask) reg |= (mask) +#define CLEAR_BIT(reg, mask) reg &= (~mask) +#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask) +//#define SET_BITS(reg, mask) SET_BIT(reg, mask) +#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);} + +#define ALIGN_SIZE ( 1L<<10 ) //1K size align +#define MEM_ALIGN(addr) (((addr) + ALIGN_SIZE - 1) & ~ (ALIGN_SIZE -1) ) + +// swap marco +#define MEI_HALF_WORD_SWAP(data) {data = ((data & 0xffff)<<16) + ((data & 0xffff0000)>>16);} +#define MEI_BYTE_SWAP(data) {data = ((data & 0xff)<<24) + ((data & 0xff00)<<8)+ ((data & 0xff0000)>>8)+ ((data & 0xff000000)>>24);} + + +#ifdef CONFIG_PROC_FS +typedef struct reg_entry +{ + int *flag; + char name[30]; /* big enough to hold names */ + char description[100]; /* big enough to hold description */ + unsigned short low_ino; +} reg_entry_t; +#endif +// Swap page header describes size in 32-bit words, load location, and image offset +// for program and/or data segments +typedef struct _arc_swp_page_hdr { + u32 p_offset; //Offset bytes of progseg from beginning of image + u32 p_dest; //Destination addr of progseg on processor + u32 p_size; //Size in 32-bitwords of program segment + u32 d_offset; //Offset bytes of dataseg from beginning of image + u32 d_dest; //Destination addr of dataseg on processor + u32 d_size; //Size in 32-bitwords of data segment +} ARC_SWP_PAGE_HDR; + +/* +** Swap image header +*/ +#define GET_PROG 0 // Flag used for program mem segment +#define GET_DATA 1 // Flag used for data mem segment + +// Image header contains size of image, checksum for image, and count of +// page headers. Following that are 'count' page headers followed by +// the code and/or data segments to be loaded +typedef struct _arc_img_hdr { + u32 size; // Size of binary image in bytes + u32 checksum; // Checksum for image + u32 count; // Count of swp pages in image + ARC_SWP_PAGE_HDR page[1]; // Should be "count" pages - '1' to make compiler happy +} ARC_IMG_HDR; + +typedef struct smmu_mem_info { + int type; + int boot; + unsigned long nCopy; + unsigned long size; + unsigned char *address; + unsigned char *org_address; +} smmu_mem_info_t; + +#ifdef __KERNEL__ +typedef struct ifx_mei_device_private { + int modem_ready; + int arcmsgav; + int cmv_reply; + int cmv_waiting; + // Mei to ARC CMV count, reply count, ARC Indicator count + int modem_ready_cnt; + int cmv_count; + int reply_count; + unsigned long image_size; + int nBar; + u16 Recent_indicator[MSG_LENGTH]; + + u16 CMV_RxMsg[MSG_LENGTH] __attribute__ ((aligned (4))); + + smmu_mem_info_t adsl_mem_info[MAX_BAR_REGISTERS]; + ARC_IMG_HDR *img_hdr; + // to wait for arc cmv reply, sleep on wait_queue_arcmsgav; + wait_queue_head_t wait_queue_arcmsgav; + wait_queue_head_t wait_queue_modemready; + struct semaphore mei_cmv_sema; +} ifx_mei_device_private_t; +#endif +typedef struct winhost_message { + union { + u16 RxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + u16 TxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + } msg; +} DSL_DEV_WinHost_Message_t; +/******************************************************************************************************** + * DSL CPE API Driver Stack Interface Definitions + * *****************************************************************************************************/ +/** IOCTL codes for bsp driver */ +#define DSL_IOC_MEI_BSP_MAGIC 's' + +#define DSL_FIO_BSP_DSL_START _IO (DSL_IOC_MEI_BSP_MAGIC, 0) +#define DSL_FIO_BSP_RUN _IO (DSL_IOC_MEI_BSP_MAGIC, 1) +#define DSL_FIO_BSP_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 2) +#define DSL_FIO_BSP_RESET _IO (DSL_IOC_MEI_BSP_MAGIC, 3) +#define DSL_FIO_BSP_REBOOT _IO (DSL_IOC_MEI_BSP_MAGIC, 4) +#define DSL_FIO_BSP_HALT _IO (DSL_IOC_MEI_BSP_MAGIC, 5) +#define DSL_FIO_BSP_BOOTDOWNLOAD _IO (DSL_IOC_MEI_BSP_MAGIC, 6) +#define DSL_FIO_BSP_JTAG_ENABLE _IO (DSL_IOC_MEI_BSP_MAGIC, 7) +#define DSL_FIO_FREE_RESOURCE _IO (DSL_IOC_MEI_BSP_MAGIC, 8) +#define DSL_FIO_ARC_MUX_TEST _IO (DSL_IOC_MEI_BSP_MAGIC, 9) +#define DSL_FIO_BSP_REMOTE _IOW (DSL_IOC_MEI_BSP_MAGIC, 10, u32) +#define DSL_FIO_BSP_GET_BASE_ADDRESS _IOR (DSL_IOC_MEI_BSP_MAGIC, 11, u32) +#define DSL_FIO_BSP_IS_MODEM_READY _IOR (DSL_IOC_MEI_BSP_MAGIC, 12, u32) +#define DSL_FIO_BSP_GET_VERSION _IOR (DSL_IOC_MEI_BSP_MAGIC, 13, DSL_DEV_Version_t) +#define DSL_FIO_BSP_CMV_WINHOST _IOWR(DSL_IOC_MEI_BSP_MAGIC, 14, DSL_DEV_WinHost_Message_t) +#define DSL_FIO_BSP_CMV_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 15, DSL_DEV_MeiReg_t) +#define DSL_FIO_BSP_CMV_WRITE _IOW (DSL_IOC_MEI_BSP_MAGIC, 16, DSL_DEV_MeiReg_t) +#define DSL_FIO_BSP_DEBUG_READ _IOWR(DSL_IOC_MEI_BSP_MAGIC, 17, DSL_DEV_MeiDebug_t) +#define DSL_FIO_BSP_DEBUG_WRITE _IOWR(DSL_IOC_MEI_BSP_MAGIC, 18, DSL_DEV_MeiDebug_t) +#define DSL_FIO_BSP_GET_CHIP_INFO _IOR (DSL_IOC_MEI_BSP_MAGIC, 19, DSL_DEV_HwVersion_t) + +#define DSL_DEV_MEIDEBUG_BUFFER_SIZES 512 + +typedef struct DSL_DEV_MeiDebug +{ + DSL_uint32_t iAddress; + DSL_uint32_t iCount; + DSL_uint32_t buffer[DSL_DEV_MEIDEBUG_BUFFER_SIZES]; +} DSL_DEV_MeiDebug_t; /* meidebug */ + +/** + * Structure is used for debug access only. + * Refer to configure option INCLUDE_ADSL_WINHOST_DEBUG */ +typedef struct struct_meireg +{ + /* + * Specifies that address for debug access */ + unsigned long iAddress; + /* + * Specifies the pointer to the data that has to be written or returns a + * pointer to the data that has been read out*/ + unsigned long iData; +} DSL_DEV_MeiReg_t; /* meireg */ + +typedef struct DSL_DEV_Device +{ + DSL_int_t nInUse; /* modem state, update by bsp driver, */ + DSL_void_t *pPriv; + DSL_uint32_t base_address; /* mei base address */ + DSL_int_t nIrq[2]; /* irq number */ +#define IFX_DFEIR 0 +#define IFX_DYING_GASP 1 + DSL_DEV_MeiDebug_t lop_debugwr; /* dying gasp */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) + struct module *owner; +#endif +} DSL_DEV_Device_t; /* ifx_adsl_device_t */ + +#define DSL_DEV_PRIVATE(dev) ((ifx_mei_device_private_t*)(dev->pPriv)) + +typedef struct DSL_DEV_Version /* ifx_adsl_bsp_version */ +{ + unsigned long major; + unsigned long minor; + unsigned long revision; +} DSL_DEV_Version_t; /* ifx_adsl_bsp_version_t */ + +typedef struct DSL_DEV_ChipInfo +{ + unsigned long major; + unsigned long minor; +} DSL_DEV_HwVersion_t; + +typedef struct +{ + DSL_uint8_t dummy; +} DSL_DEV_DeviceConfig_t; + +/** error code definitions */ +typedef enum DSL_DEV_MeiError +{ + DSL_DEV_MEI_ERR_SUCCESS = 0, + DSL_DEV_MEI_ERR_FAILURE = -1, + DSL_DEV_MEI_ERR_MAILBOX_FULL = -2, + DSL_DEV_MEI_ERR_MAILBOX_EMPTY = -3, + DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT = -4 +} DSL_DEV_MeiError_t; /* MEI_ERROR */ + +typedef enum { + DSL_BSP_MEMORY_READ=0, + DSL_BSP_MEMORY_WRITE, +} DSL_BSP_MemoryAccessType_t; /* ifx_adsl_memory_access_type_t */ + +typedef enum +{ + DSL_LED_LINK_ID=0, + DSL_LED_DATA_ID +} DSL_DEV_LedId_t; /* ifx_adsl_led_id_t */ + +typedef enum +{ + DSL_LED_LINK_TYPE=0, + DSL_LED_DATA_TYPE +} DSL_DEV_LedType_t; /* ifx_adsl_led_type_t */ + +typedef enum +{ + DSL_LED_HD_CPU=0, + DSL_LED_HD_FW +} DSL_DEV_LedHandler_t; /* ifx_adsl_led_handler_t */ + +typedef enum { + DSL_LED_ON=0, + DSL_LED_OFF, + DSL_LED_FLASH, +} DSL_DEV_LedMode_t; /* ifx_adsl_led_mode_t */ + +typedef enum { + DSL_CPU_HALT=0, + DSL_CPU_RUN, + DSL_CPU_RESET, +} DSL_DEV_CpuMode_t; /* ifx_adsl_cpu_mode_t */ + +#if 0 +typedef enum { + DSL_BSP_EVENT_DYING_GASP = 0, + DSL_BSP_EVENT_CEOC_IRQ, +} DSL_BSP_Event_id_t; /* ifx_adsl_event_id_t */ + +typedef union DSL_BSP_CB_Param +{ + DSL_uint32_t nIrqMessage; +} DSL_BSP_CB_Param_t; /* ifx_adsl_cbparam_t */ + +typedef struct DSL_BSP_CB_Event +{ + DSL_BSP_Event_id_t nID; + DSL_DEV_Device_t *pDev; + DSL_BSP_CB_Param_t *pParam; +} DSL_BSP_CB_Event_t; /* ifx_adsl_cb_event_t */ +#endif + +/* external functions (from the BSP Driver) */ +extern DSL_DEV_Device_t* DSL_BSP_DriverHandleGet(int, int); +extern DSL_int_t DSL_BSP_DriverHandleDelete(DSL_DEV_Device_t *); +extern DSL_DEV_MeiError_t DSL_BSP_FWDownload(DSL_DEV_Device_t *, const DSL_char_t *, DSL_uint32_t, DSL_int32_t *, DSL_int32_t *); +extern int DSL_BSP_KernelIoctls(DSL_DEV_Device_t *, unsigned int, unsigned long); +extern DSL_DEV_MeiError_t DSL_BSP_SendCMV(DSL_DEV_Device_t *, DSL_uint16_t *, DSL_int_t, DSL_uint16_t *); +extern DSL_DEV_MeiError_t DSL_BSP_AdslLedInit(DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t); +extern DSL_DEV_MeiError_t DSL_BSP_Showtime(DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t); +extern int DSL_BSP_ATMLedCBRegister( int (*ifx_adsl_ledcallback)(void)); +extern DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess(DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t *, DSL_uint32_t); +extern volatile DSL_DEV_Device_t *adsl_dev; + +/** + * Dummy structure by now to show mechanism of extended data that will be + * provided within event callback itself. + * */ +typedef struct +{ + /** + * Dummy value */ + DSL_uint32_t nDummy1; +} DSL_BSP_CB_Event1DataDummy_t; + +/** + * Dummy structure by now to show mechanism of extended data that will be + * provided within event callback itself. + * */ +typedef struct +{ + /** + * Dummy value */ + DSL_uint32_t nDummy2; +} DSL_BSP_CB_Event2DataDummy_t; + +/** + * encapsulate all data structures that are necessary for status event + * callbacks. + * */ +typedef union +{ + DSL_BSP_CB_Event1DataDummy_t dataEvent1; + DSL_BSP_CB_Event2DataDummy_t dataEvent2; +} DSL_BSP_CB_DATA_Union_t; + + +typedef enum +{ + /** + * Informs the upper layer driver (DSL CPE API) about a reboot request from the + * firmware. + * \note This event does NOT include any additional data. + * More detailed information upon reboot reason has to be requested from + * upper layer software via CMV (INFO 109) if necessary. */ + DSL_BSP_CB_FIRST = 0, + DSL_BSP_CB_DYING_GASP, + DSL_BSP_CB_CEOC_IRQ, + DSL_BSP_CB_FIRMWARE_REBOOT, + /** + * Delimiter only */ + DSL_BSP_CB_LAST +} DSL_BSP_CB_Type_t; + +/** + * Specifies the common event type that has to be used for registering and + * signalling of interrupts/autonomous status events from MEI BSP Driver. + * + * \param pDev + * Context pointer from MEI BSP Driver. + * + * \param IFX_ADSL_BSP_CallbackType_t + * Specifies the event callback type (reason of callback). Regrading to the + * setting of this value the data which is included in the following union + * might have different meanings. + * Please refer to the description of the union to get information about the + * meaning of the included data. + * + * \param pData + * Data according to \ref DSL_BSP_CB_DATA_Union_t. + * If this pointer is NULL there is no additional data available. + * + * \return depending on event + */ +typedef int (*DSL_BSP_EventCallback_t) +( + DSL_DEV_Device_t *pDev, + DSL_BSP_CB_Type_t nCallbackType, + DSL_BSP_CB_DATA_Union_t *pData +); + +typedef struct { + DSL_BSP_EventCallback_t function; + DSL_BSP_CB_Type_t event; + DSL_BSP_CB_DATA_Union_t *pData; +} DSL_BSP_EventCallBack_t; + +extern int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *); +extern int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *); + +/** Modem states */ +#define DSL_DEV_STAT_InitState 0x0000 +#define DSL_DEV_STAT_ReadyState 0x0001 +#define DSL_DEV_STAT_FailState 0x0002 +#define DSL_DEV_STAT_IdleState 0x0003 +#define DSL_DEV_STAT_QuietState 0x0004 +#define DSL_DEV_STAT_GhsState 0x0005 +#define DSL_DEV_STAT_FullInitState 0x0006 +#define DSL_DEV_STAT_ShowTimeState 0x0007 +#define DSL_DEV_STAT_FastRetrainState 0x0008 +#define DSL_DEV_STAT_LoopDiagMode 0x0009 +#define DSL_DEV_STAT_ShortInit 0x000A /* Bis short initialization */ + +#define DSL_DEV_STAT_CODESWAP_COMPLETE 0x0002 + +#endif //IFXMIPS_MEI_H diff --git a/package/system/ltq-dsl/src/lantiq_mei.c b/package/system/ltq-dsl/src/lantiq_mei.c new file mode 100644 index 0000000000..aadb098c6d --- /dev/null +++ b/package/system/ltq-dsl/src/lantiq_mei.c @@ -0,0 +1,3038 @@ +/****************************************************************************** + + Copyright (c) 2009 + Infineon Technologies AG + Am Campeon 1-12; 81726 Munich, Germany + + For licensing information, see the file 'LICENSE' in the root folder of + this software module. + +******************************************************************************/ + +/*! + \defgroup AMAZON_S_MEI Amazon-S MEI Driver Module + \brief Amazon-S MEI driver module + */ + +/*! + \defgroup Internal Compile Parametere + \ingroup AMAZON_S_MEI + \brief exported functions for other driver use + */ + +/*! + \file amazon_s_mei_bsp.c + \ingroup AMAZON_S_MEI + \brief Amazon-S MEI driver file + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) +#include <linux/utsrelease.h> +#else +#include <generated/utsrelease.h> +#endif +#include <linux/types.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/sched.h> +#include <asm/uaccess.h> +#include <asm/hardirq.h> + +#include <lantiq_soc.h> +#include "ifxmips_atm.h" +#define IFX_MEI_BSP +#include "ifxmips_mei_interface.h" + +/*#define LTQ_RCU_RST IFX_RCU_RST_REQ +#define LTQ_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG +#define LTQ_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE +#define LTQ_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE +#define IFXMIPS_FUSE_BASE_ADDR IFX_FUSE_BASE_ADDR +#define IFXMIPS_ICU_IM0_IER IFX_ICU_IM0_IER +#define IFXMIPS_ICU_IM2_IER IFX_ICU_IM2_IER +#define LTQ_MEI_INT IFX_MEI_INT +#define LTQ_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT +#define LTQ_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS +#define IFXMIPS_PMU_PWDCR IFX_PMU_PWDCR +#define IFXMIPS_MPS_CHIPID IFX_MPS_CHIPID + +#define ifxmips_port_reserve_pin ifx_gpio_pin_reserve +#define ifxmips_port_set_dir_in ifx_gpio_dir_in_set +#define ifxmips_port_clear_altsel0 ifx_gpio_altsel0_set +#define ifxmips_port_clear_altsel1 ifx_gpio_altsel1_clear +#define ifxmips_port_set_open_drain ifx_gpio_open_drain_clear +#define ifxmips_port_free_pin ifx_gpio_pin_free +#define ifxmips_mask_and_ack_irq bsp_mask_and_ack_irq +#define IFXMIPS_MPS_CHIPID_VERSION_GET IFX_MCD_CHIPID_VERSION_GET +#define ltq_r32(reg) __raw_readl(reg) +#define ltq_w32(val, reg) __raw_writel(val, reg) +#define ltq_w32_mask(clear, set, reg) ltq_w32((ltq_r32(reg) & ~clear) | set, reg) +*/ + +#define LTQ_RCU_RST_REQ_DFE (1 << 7) +#define LTQ_RCU_RST_REQ_AFE (1 << 11) + +#define LTQ_PMU_BASE (KSEG1 + LTQ_PMU_BASE_ADDR) +#define LTQ_RCU_BASE (KSEG1 + LTQ_RCU_BASE_ADDR) +#define LTQ_ICU_BASE (KSEG1 + LTQ_ICU_BASE_ADDR) + +#define LTQ_PMU_PWDCR ((u32 *)(LTQ_PMU_BASE + 0x001C)) +#define LTQ_PMU_PWDSR ((u32 *)(LTQ_PMU_BASE + 0x0020)) +#define LTQ_RCU_RST ((u32 *)(LTQ_RCU_BASE + 0x0010)) +#define LTQ_RCU_RST_ALL 0x40000000 + +#define LTQ_ICU_IM0_ISR ((u32 *)(LTQ_ICU_BASE + 0x0000)) +#define LTQ_ICU_IM0_IER ((u32 *)(LTQ_ICU_BASE + 0x0008)) +#define LTQ_ICU_IM0_IOSR ((u32 *)(LTQ_ICU_BASE + 0x0010)) +#define LTQ_ICU_IM0_IRSR ((u32 *)(LTQ_ICU_BASE + 0x0018)) +#define LTQ_ICU_IM0_IMR ((u32 *)(LTQ_ICU_BASE + 0x0020)) + + +#define LTQ_ICU_IM1_ISR ((u32 *)(LTQ_ICU_BASE + 0x0028)) +#define LTQ_ICU_IM2_ISR ((u32 *)(LTQ_ICU_BASE + 0x0050)) +#define LTQ_ICU_IM3_ISR ((u32 *)(LTQ_ICU_BASE + 0x0078)) +#define LTQ_ICU_IM4_ISR ((u32 *)(LTQ_ICU_BASE + 0x00A0)) + +#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR) +#define LTQ_ICU_IM2_IER (LTQ_ICU_IM0_IER + LTQ_ICU_OFFSET) + +#define IFX_MEI_EMSG(fmt, args...) pr_err("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args) +#define IFX_MEI_DMSG(fmt, args...) pr_debug("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args) + +#define LTQ_FUSE_BASE (KSEG1 + 0x1F107354) + +#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK +//#define DFE_MEM_TEST +//#define DFE_PING_TEST +#define DFE_ATM_LOOPBACK + + +#ifdef DFE_ATM_LOOPBACK +#include <asm/ifxmips/ifxmips_mei_fw_loopback.h> +#endif + +void dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev); + +#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK + +DSL_DEV_Version_t bsp_mei_version = { + major: 5, + minor: 0, + revision:0 +}; +DSL_DEV_HwVersion_t bsp_chip_info; + +#define IFX_MEI_DEVNAME "ifx_mei" +#define BSP_MAX_DEVICES 1 + +DSL_DEV_MeiError_t DSL_BSP_FWDownload (DSL_DEV_Device_t *, const char *, unsigned long, long *, long *); +DSL_DEV_MeiError_t DSL_BSP_Showtime (DSL_DEV_Device_t *, DSL_uint32_t, DSL_uint32_t); +DSL_DEV_MeiError_t DSL_BSP_AdslLedInit (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedType_t, DSL_DEV_LedHandler_t); +//DSL_DEV_MeiError_t DSL_BSP_AdslLedSet (DSL_DEV_Device_t *, DSL_DEV_LedId_t, DSL_DEV_LedMode_t); +DSL_DEV_MeiError_t DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t *, DSL_BSP_MemoryAccessType_t, DSL_uint32_t, DSL_uint32_t*, DSL_uint32_t); +DSL_DEV_MeiError_t DSL_BSP_SendCMV (DSL_DEV_Device_t *, u16 *, int, u16 *); + +int DSL_BSP_KernelIoctls (DSL_DEV_Device_t *, unsigned int, unsigned long); + +static DSL_DEV_MeiError_t IFX_MEI_RunAdslModem (DSL_DEV_Device_t *); +static DSL_DEV_MeiError_t IFX_MEI_CpuModeSet (DSL_DEV_Device_t *, DSL_DEV_CpuMode_t); +static DSL_DEV_MeiError_t IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *); +static DSL_DEV_MeiError_t IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *, int); +static DSL_DEV_MeiError_t IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *, int); + +static int IFX_MEI_GetPage (DSL_DEV_Device_t *, u32, u32, u32, u32 *, u32 *); +static int IFX_MEI_BarUpdate (DSL_DEV_Device_t *, int); + +static ssize_t IFX_MEI_Write (DSL_DRV_file_t *, const char *, size_t, loff_t *); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) +static int IFX_MEI_UserIoctls (DSL_DRV_inode_t *, DSL_DRV_file_t *, unsigned int, unsigned long); +#else +static int IFX_MEI_UserIoctls (DSL_DRV_file_t *, unsigned int, unsigned long); +#endif +static int IFX_MEI_Open (DSL_DRV_inode_t *, DSL_DRV_file_t *); +static int IFX_MEI_Release (DSL_DRV_inode_t *, DSL_DRV_file_t *); + +void AMAZON_SE_MEI_ARC_MUX_Test(void); + +#ifdef CONFIG_PROC_FS +static int IFX_MEI_ProcRead (struct file *, char *, size_t, loff_t *); +static ssize_t IFX_MEI_ProcWrite (struct file *, const char *, size_t, loff_t *); + +#define PROC_ITEMS 11 +#define MEI_DIRNAME "ifxmips_mei" + +static struct proc_dir_entry *meidir; +static struct file_operations IFX_MEI_ProcOperations = { + read:IFX_MEI_ProcRead, + write:IFX_MEI_ProcWrite, +}; +static reg_entry_t regs[BSP_MAX_DEVICES][PROC_ITEMS]; //total items to be monitored by /proc/mei +#define NUM_OF_REG_ENTRY (sizeof(regs[0])/sizeof(reg_entry_t)) +#endif //CONFIG_PROC_FS + +void IFX_MEI_ARC_MUX_Test(void); + +static int adsl_dummy_ledcallback(void); + +int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL; +EXPORT_SYMBOL(ifx_mei_atm_showtime_enter); + +int (*ifx_mei_atm_showtime_exit)(void) = NULL; +EXPORT_SYMBOL(ifx_mei_atm_showtime_exit); + +static int (*g_adsl_ledcallback)(void) = adsl_dummy_ledcallback; + +static unsigned int g_tx_link_rate[2] = {0}; + +static void *g_xdata_addr = NULL; + +static u32 *mei_arc_swap_buff = NULL; // holding swap pages + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) +extern void ltq_mask_and_ack_irq(unsigned int irq_nr); +#define MEI_MASK_AND_ACK_IRQ ltq_mask_and_ack_irq +#else +extern void ltq_mask_and_ack_irq(struct irq_data *d); +static void inline MEI_MASK_AND_ACK_IRQ(int x) +{ + struct irq_data d; + d.irq = x; + ltq_mask_and_ack_irq(&d); +} +#endif +#define MEI_MAJOR 105 +static int dev_major = MEI_MAJOR; + +static struct file_operations bsp_mei_operations = { + owner:THIS_MODULE, + open:IFX_MEI_Open, + release:IFX_MEI_Release, + write:IFX_MEI_Write, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + ioctl:IFX_MEI_UserIoctls, +#else + unlocked_ioctl:IFX_MEI_UserIoctls, +#endif +}; + +static DSL_DEV_Device_t dsl_devices[BSP_MAX_DEVICES]; + +static ifx_mei_device_private_t + sDanube_Mei_Private[BSP_MAX_DEVICES]; + +static DSL_BSP_EventCallBack_t dsl_bsp_event_callback[DSL_BSP_CB_LAST + 1]; + +/** + * Write a value to register + * This function writes a value to danube register + * + * \param ul_address The address to write + * \param ul_data The value to write + * \ingroup Internal + */ +static void +IFX_MEI_LongWordWrite (u32 ul_address, u32 ul_data) +{ + IFX_MEI_WRITE_REGISTER_L (ul_data, ul_address); + wmb(); + return; +} + +/** + * Write a value to register + * This function writes a value to danube register + * + * \param pDev the device pointer + * \param ul_address The address to write + * \param ul_data The value to write + * \ingroup Internal + */ +static void +IFX_MEI_LongWordWriteOffset (DSL_DEV_Device_t * pDev, u32 ul_address, + u32 ul_data) +{ + IFX_MEI_WRITE_REGISTER_L (ul_data, pDev->base_address + ul_address); + wmb(); + return; +} + +/** + * Read the danube register + * This function read the value from danube register + * + * \param ul_address The address to write + * \param pul_data Pointer to the data + * \ingroup Internal + */ +static void +IFX_MEI_LongWordRead (u32 ul_address, u32 * pul_data) +{ + *pul_data = IFX_MEI_READ_REGISTER_L (ul_address); + rmb(); + return; +} + +/** + * Read the danube register + * This function read the value from danube register + * + * \param pDev the device pointer + * \param ul_address The address to write + * \param pul_data Pointer to the data + * \ingroup Internal + */ +static void +IFX_MEI_LongWordReadOffset (DSL_DEV_Device_t * pDev, u32 ul_address, + u32 * pul_data) +{ + *pul_data = IFX_MEI_READ_REGISTER_L (pDev->base_address + ul_address); + rmb(); + return; +} + +/** + * Write several DWORD datas to ARC memory via ARC DMA interface + * This function writes several DWORD datas to ARC memory via DMA interface. + * + * \param pDev the device pointer + * \param destaddr The address to write + * \param databuff Pointer to the data buffer + * \param databuffsize Number of DWORDs to write + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_DMAWrite (DSL_DEV_Device_t * pDev, u32 destaddr, + u32 * databuff, u32 databuffsize) +{ + u32 *p = databuff; + u32 temp; + + if (destaddr & 3) + return DSL_DEV_MEI_ERR_FAILURE; + + // Set the write transfer address + IFX_MEI_LongWordWriteOffset (pDev, ME_DX_AD, destaddr); + + // Write the data pushed across DMA + while (databuffsize--) { + temp = *p; + if (destaddr == MEI_TO_ARC_MAILBOX) + MEI_HALF_WORD_SWAP (temp); + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_DATA, temp); + p++; + } + + return DSL_DEV_MEI_ERR_SUCCESS; + +} + +/** + * Read several DWORD datas from ARC memory via ARC DMA interface + * This function reads several DWORD datas from ARC memory via DMA interface. + * + * \param pDev the device pointer + * \param srcaddr The address to read + * \param databuff Pointer to the data buffer + * \param databuffsize Number of DWORDs to read + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_DMARead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff, + u32 databuffsize) +{ + u32 *p = databuff; + u32 temp; + + if (srcaddr & 3) + return DSL_DEV_MEI_ERR_FAILURE; + + // Set the read transfer address + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DX_AD, srcaddr); + + // Read the data popped across DMA + while (databuffsize--) { + IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DX_DATA, &temp); + if (databuff == (u32 *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg) // swap half word + MEI_HALF_WORD_SWAP (temp); + *p = temp; + p++; + } + + return DSL_DEV_MEI_ERR_SUCCESS; + +} + +/** + * Switch the ARC control mode + * This function switchs the ARC control mode to JTAG mode or MEI mode + * + * \param pDev the device pointer + * \param mode The mode want to switch: JTAG_MASTER_MODE or MEI_MASTER_MODE. + * \ingroup Internal + */ +static void +IFX_MEI_ControlModeSet (DSL_DEV_Device_t * pDev, int mode) +{ + u32 temp = 0x0; + + IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_MASTER, &temp); + switch (mode) { + case JTAG_MASTER_MODE: + temp &= ~(HOST_MSTR); + break; + case MEI_MASTER_MODE: + temp |= (HOST_MSTR); + break; + default: + IFX_MEI_EMSG ("IFX_MEI_ControlModeSet: unkonwn mode [%d]\n", mode); + return; + } + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_MASTER, temp); +} + +/** + * Disable ARC to MEI interrupt + * + * \param pDev the device pointer + * \ingroup Internal + */ +static void +IFX_MEI_IRQDisable (DSL_DEV_Device_t * pDev) +{ + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, 0x0); +} + +/** + * Eable ARC to MEI interrupt + * + * \param pDev the device pointer + * \ingroup Internal + */ +static void +IFX_MEI_IRQEnable (DSL_DEV_Device_t * pDev) +{ + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_MASK, MSGAV_EN); +} + +/** + * Poll for transaction complete signal + * This function polls and waits for transaction complete signal. + * + * \param pDev the device pointer + * \ingroup Internal + */ +static void +meiPollForDbgDone (DSL_DEV_Device_t * pDev) +{ + u32 query = 0; + int i = 0; + + while (i < WHILE_DELAY) { + IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ARC2ME_STAT, &query); + query &= (ARC_TO_MEI_DBG_DONE); + if (query) + break; + i++; + if (i == WHILE_DELAY) { + IFX_MEI_EMSG ("PollforDbg fail!\n"); + } + } + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_DBG_DONE); // to clear this interrupt +} + +/** + * ARC Debug Memory Access for a single DWORD reading. + * This function used for direct, address-based access to ARC memory. + * + * \param pDev the device pointer + * \param DEC_mode ARC memory space to used + * \param address Address to read + * \param data Pointer to data + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +_IFX_MEI_DBGLongWordRead (DSL_DEV_Device_t * pDev, u32 DEC_mode, + u32 address, u32 * data) +{ + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode); + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_RD_AD, address); + meiPollForDbgDone (pDev); + IFX_MEI_LongWordReadOffset (pDev, (u32) ME_DBG_DATA, data); + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * ARC Debug Memory Access for a single DWORD writing. + * This function used for direct, address-based access to ARC memory. + * + * \param pDev the device pointer + * \param DEC_mode ARC memory space to used + * \param address The address to write + * \param data The data to write + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +_IFX_MEI_DBGLongWordWrite (DSL_DEV_Device_t * pDev, u32 DEC_mode, + u32 address, u32 data) +{ + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DECODE, DEC_mode); + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_WR_AD, address); + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_DBG_DATA, data); + meiPollForDbgDone (pDev); + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * ARC Debug Memory Access for writing. + * This function used for direct, address-based access to ARC memory. + * + * \param pDev the device pointer + * \param destaddr The address to read + * \param databuffer Pointer to data + * \param databuffsize The number of DWORDs to read + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ + +static DSL_DEV_MeiError_t +IFX_MEI_DebugWrite (DSL_DEV_Device_t * pDev, u32 destaddr, + u32 * databuff, u32 databuffsize) +{ + u32 i; + u32 temp = 0x0; + u32 address = 0x0; + u32 *buffer = 0x0; + + // Open the debug port before DMP memory write + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + + // For the requested length, write the address and write the data + address = destaddr; + buffer = databuff; + for (i = 0; i < databuffsize; i++) { + temp = *buffer; + _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK, address, temp); + address += 4; + buffer++; + } + + // Close the debug port after DMP memory write + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * ARC Debug Memory Access for reading. + * This function used for direct, address-based access to ARC memory. + * + * \param pDev the device pointer + * \param srcaddr The address to read + * \param databuffer Pointer to data + * \param databuffsize The number of DWORDs to read + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_DebugRead (DSL_DEV_Device_t * pDev, u32 srcaddr, u32 * databuff, u32 databuffsize) +{ + u32 i; + u32 temp = 0x0; + u32 address = 0x0; + u32 *buffer = 0x0; + + // Open the debug port before DMP memory read + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + + // For the requested length, write the address and read the data + address = srcaddr; + buffer = databuff; + for (i = 0; i < databuffsize; i++) { + _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK, address, &temp); + *buffer = temp; + address += 4; + buffer++; + } + + // Close the debug port after DMP memory read + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * Send a message to ARC MailBox. + * This function sends a message to ARC Mailbox via ARC DMA interface. + * + * \param pDev the device pointer + * \param msgsrcbuffer Pointer to message. + * \param msgsize The number of words to write. + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_MailboxWrite (DSL_DEV_Device_t * pDev, u16 * msgsrcbuffer, + u16 msgsize) +{ + int i; + u32 arc_mailbox_status = 0x0; + u32 temp = 0; + DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS; + + // Write to mailbox + meiMailboxError = + IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOX, (u32 *) msgsrcbuffer, msgsize / 2); + meiMailboxError = + IFX_MEI_DMAWrite (pDev, MEI_TO_ARC_MAILBOXR, (u32 *) (&temp), 1); + + // Notify arc that mailbox write completed + DSL_DEV_PRIVATE(pDev)->cmv_waiting = 1; + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV); + + i = 0; + while (i < WHILE_DELAY) { // wait for ARC to clear the bit + IFX_MEI_LongWordReadOffset (pDev, (u32) ME_ME2ARC_INT, &arc_mailbox_status); + if ((arc_mailbox_status & MEI_TO_ARC_MSGAV) != MEI_TO_ARC_MSGAV) + break; + i++; + if (i == WHILE_DELAY) { + IFX_MEI_EMSG (">>> Timeout waiting for ARC to clear MEI_TO_ARC_MSGAV!!!" + " MEI_TO_ARC message size = %d DWORDs <<<\n", msgsize/2); + meiMailboxError = DSL_DEV_MEI_ERR_FAILURE; + } + } + + return meiMailboxError; +} + +/** + * Read a message from ARC MailBox. + * This function reads a message from ARC Mailbox via ARC DMA interface. + * + * \param pDev the device pointer + * \param msgsrcbuffer Pointer to message. + * \param msgsize The number of words to read + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_MailboxRead (DSL_DEV_Device_t * pDev, u16 * msgdestbuffer, + u16 msgsize) +{ + DSL_DEV_MeiError_t meiMailboxError = DSL_DEV_MEI_ERR_SUCCESS; + // Read from mailbox + meiMailboxError = + IFX_MEI_DMARead (pDev, ARC_TO_MEI_MAILBOX, (u32 *) msgdestbuffer, msgsize / 2); + + // Notify arc that mailbox read completed + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV); + + return meiMailboxError; +} + +/** + * Download boot pages to ARC. + * This function downloads boot pages to ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_DownloadBootPages (DSL_DEV_Device_t * pDev) +{ + int boot_loop; + int page_size; + u32 dest_addr; + + /* + ** DMA the boot code page(s) + */ + + for (boot_loop = 1; + boot_loop < + (DSL_DEV_PRIVATE(pDev)->img_hdr-> count); boot_loop++) { + if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].p_size) & BOOT_FLAG) { + page_size = IFX_MEI_GetPage (pDev, boot_loop, + GET_PROG, MAXSWAPSIZE, + mei_arc_swap_buff, + &dest_addr); + if (page_size > 0) { + IFX_MEI_DMAWrite (pDev, dest_addr, + mei_arc_swap_buff, + page_size); + } + } + if ((DSL_DEV_PRIVATE(pDev)-> img_hdr->page[boot_loop].d_size) & BOOT_FLAG) { + page_size = IFX_MEI_GetPage (pDev, boot_loop, + GET_DATA, MAXSWAPSIZE, + mei_arc_swap_buff, + &dest_addr); + if (page_size > 0) { + IFX_MEI_DMAWrite (pDev, dest_addr, + mei_arc_swap_buff, + page_size); + } + } + } + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * Initial efuse rar. + **/ +static void +IFX_MEI_FuseInit (DSL_DEV_Device_t * pDev) +{ + u32 data = 0; + IFX_MEI_DMAWrite (pDev, IRAM0_BASE, &data, 1); + IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, &data, 1); + IFX_MEI_DMAWrite (pDev, IRAM1_BASE, &data, 1); + IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, &data, 1); + IFX_MEI_DMAWrite (pDev, BRAM_BASE, &data, 1); + IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, &data, 1); + IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, &data, 1); + IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, &data, 1); +} + +/** + * efuse rar program + **/ +static void +IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev) +{ + u32 reg_data, fuse_value; + int i = 0; + + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); + while ((reg_data & 0x10000000) == 0) { + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); + i++; + /* 0x4000 translate to about 16 ms@111M, so should be enough */ + if (i == 0x4000) + return; + } + // STEP a: Prepare memory for external accesses + // Write fuse_en bit24 + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); + IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | (1 << 24)); + + IFX_MEI_FuseInit (pDev); + for (i = 0; i < 4; i++) { + IFX_MEI_LongWordRead ((u32) (LTQ_FUSE_BASE) + i * 4, &fuse_value); + switch (fuse_value & 0xF0000) { + case 0x80000: + reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) | + (RX_DILV_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE, ®_data, 1); + break; + case 0x90000: + reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) | + (RX_DILV_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, ADSL_DILV_BASE + 4, ®_data, 1); + break; + case 0xA0000: + reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) | + (IRAM0_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, IRAM0_BASE, ®_data, 1); + break; + case 0xB0000: + reg_data = ((fuse_value & IRAM0_ADDR_BIT_MASK) | + (IRAM0_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, IRAM0_BASE + 4, ®_data, 1); + break; + case 0xC0000: + reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) | + (IRAM1_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, IRAM1_BASE, ®_data, 1); + break; + case 0xD0000: + reg_data = ((fuse_value & IRAM1_ADDR_BIT_MASK) | + (IRAM1_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, IRAM1_BASE + 4, ®_data, 1); + break; + case 0xE0000: + reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) | + (BRAM_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, BRAM_BASE, ®_data, 1); + break; + case 0xF0000: + reg_data = ((fuse_value & BRAM_ADDR_BIT_MASK) | + (BRAM_ADDR_BIT_MASK + 0x1)); + IFX_MEI_DMAWrite (pDev, BRAM_BASE + 4, ®_data, 1); + break; + default: // PPE efuse + break; + } + } + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); + IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data & ~(1 << 24)); + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); +} + +/** + * Enable DFE Clock + * This function enables DFE Clock + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_EnableCLK (DSL_DEV_Device_t * pDev) +{ + u32 arc_debug_data = 0; + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + //enable ac_clk signal + _IFX_MEI_DBGLongWordRead (pDev, ME_DBG_DECODE_DMP1_MASK, + CRI_CCR0, &arc_debug_data); + arc_debug_data |= ACL_CLK_MODE_ENABLE; + _IFX_MEI_DBGLongWordWrite (pDev, ME_DBG_DECODE_DMP1_MASK, + CRI_CCR0, arc_debug_data); + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * Halt the ARC. + * This function halts the ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_HaltArc (DSL_DEV_Device_t * pDev) +{ + u32 arc_debug_data = 0x0; + + // Switch arc control from JTAG mode to MEI mode + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK, + ARC_DEBUG, &arc_debug_data); + arc_debug_data |= ARC_DEBUG_HALT; + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, + ARC_DEBUG, arc_debug_data); + // Switch arc control from MEI mode to JTAG mode + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + MEI_WAIT (10); + + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * Run the ARC. + * This function runs the ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_RunArc (DSL_DEV_Device_t * pDev) +{ + u32 arc_debug_data = 0x0; + + // Switch arc control from JTAG mode to MEI mode- write '1' to bit0 + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + _IFX_MEI_DBGLongWordRead (pDev, MEI_DEBUG_DEC_AUX_MASK, + AUX_STATUS, &arc_debug_data); + + // Write debug data reg with content ANDd with 0xFDFFFFFF (halt bit cleared) + arc_debug_data &= ~ARC_AUX_HALT; + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, + AUX_STATUS, arc_debug_data); + + // Switch arc control from MEI mode to JTAG mode- write '0' to bit0 + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + // Enable mask for arc codeswap interrupts + IFX_MEI_IRQEnable (pDev); + + return DSL_DEV_MEI_ERR_SUCCESS; + +} + +/** + * Reset the ARC. + * This function resets the ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev) +{ + u32 arc_debug_data = 0; + + IFX_MEI_HaltArc (pDev); + + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &arc_debug_data); + IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, + arc_debug_data | LTQ_RCU_RST_REQ_DFE | LTQ_RCU_RST_REQ_AFE); + + // reset ARC + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET); + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, 0); + + IFX_MEI_IRQDisable (pDev); + + IFX_MEI_EnableCLK (pDev); + +#if 0 + // reset part of PPE + *(unsigned long *) (BSP_PPE32_SRST) = 0xC30; + *(unsigned long *) (BSP_PPE32_SRST) = 0xFFF; +#endif + + DSL_DEV_PRIVATE(pDev)->modem_ready = 0; + + return DSL_DEV_MEI_ERR_SUCCESS; +} + +DSL_DEV_MeiError_t +DSL_BSP_Showtime (DSL_DEV_Device_t * dev, DSL_uint32_t rate_fast, DSL_uint32_t rate_intl) +{ + struct port_cell_info port_cell = {0}; + + IFX_MEI_EMSG ("Datarate US intl = %d, fast = %d\n", (int)rate_intl, + (int)rate_fast); + + if ( rate_fast ) + g_tx_link_rate[0] = rate_fast / (53 * 8); + if ( rate_intl ) + g_tx_link_rate[1] = rate_intl / (53 * 8); + + if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ) { + IFX_MEI_EMSG ("Got rate fail.\n"); + } + + if ( ifx_mei_atm_showtime_enter ) + { + port_cell.port_num = 2; + port_cell.tx_link_rate[0] = g_tx_link_rate[0]; + port_cell.tx_link_rate[1] = g_tx_link_rate[1]; + ifx_mei_atm_showtime_enter(&port_cell, g_xdata_addr); + } + else + { + IFX_MEI_EMSG("no hookup from ATM driver to set cell rate\n"); + } + + return DSL_DEV_MEI_ERR_SUCCESS; +}; + +/** + * Reset/halt/run the DFE. + * This function provide operations to reset/halt/run the DFE. + * + * \param pDev the device pointer + * \param mode which operation want to do + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_CpuModeSet (DSL_DEV_Device_t *pDev, + DSL_DEV_CpuMode_t mode) +{ + DSL_DEV_MeiError_t err_ret = DSL_DEV_MEI_ERR_FAILURE; + switch (mode) { + case DSL_CPU_HALT: + err_ret = IFX_MEI_HaltArc (pDev); + break; + case DSL_CPU_RUN: + err_ret = IFX_MEI_RunArc (pDev); + break; + case DSL_CPU_RESET: + err_ret = IFX_MEI_ResetARC (pDev); + break; + default: + break; + } + return err_ret; +} + +/** + * Accress DFE memory. + * This function provide a way to access DFE memory; + * + * \param pDev the device pointer + * \param type read or write + * \param destaddr destination address + * \param databuff pointer to hold data + * \param databuffsize size want to read/write + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +DSL_DEV_MeiError_t +DSL_BSP_MemoryDebugAccess (DSL_DEV_Device_t * pDev, + DSL_BSP_MemoryAccessType_t type, + DSL_uint32_t destaddr, DSL_uint32_t *databuff, + DSL_uint32_t databuffsize) +{ + DSL_DEV_MeiError_t meierr = DSL_DEV_MEI_ERR_SUCCESS; + switch (type) { + case DSL_BSP_MEMORY_READ: + meierr = IFX_MEI_DebugRead (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize); + break; + case DSL_BSP_MEMORY_WRITE: + meierr = IFX_MEI_DebugWrite (pDev, (u32)destaddr, (u32*)databuff, (u32)databuffsize); + break; + } + return DSL_DEV_MEI_ERR_SUCCESS; +}; + +/** + * Download boot code to ARC. + * This function downloads boot code to ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_DownloadBootCode (DSL_DEV_Device_t *pDev) +{ + IFX_MEI_IRQDisable (pDev); + + IFX_MEI_EnableCLK (pDev); + + IFX_MEI_FuseProg (pDev); //program fuse rar + + IFX_MEI_DownloadBootPages (pDev); + + return DSL_DEV_MEI_ERR_SUCCESS; +}; + +/** + * Enable Jtag debugger interface + * This function setups mips gpio to enable jtag debugger + * + * \param pDev the device pointer + * \param enable enable or disable + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable) +{ + /* + int meierr=0; + u32 reg_data; + switch (enable) { + case 1: + //reserve gpio 9, 10, 11, 14, 19 for ARC JTAG + ifxmips_port_reserve_pin (0, 9); + ifxmips_port_reserve_pin (0, 10); + ifxmips_port_reserve_pin (0, 11); + ifxmips_port_reserve_pin (0, 14); + ifxmips_port_reserve_pin (1, 3); + + ifxmips_port_set_dir_in(0, 11); + ifxmips_port_clear_altsel0(0, 11); + ifxmips_port_clear_altsel1(0, 11); + ifxmips_port_set_open_drain(0, 11); + //enable ARC JTAG + IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data); + IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | LTQ_RCU_RST_REQ_ARC_JTAG); + break; + case 0: + default: + break; + } +jtag_end: + if (meierr) + return DSL_DEV_MEI_ERR_FAILURE; +*/ + + return DSL_DEV_MEI_ERR_SUCCESS; +}; + +/** + * Enable DFE to MIPS interrupt + * This function enable DFE to MIPS interrupt + * + * \param pDev the device pointer + * \param enable enable or disable + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_AdslMailboxIRQEnable (DSL_DEV_Device_t *pDev, int enable) +{ + DSL_DEV_MeiError_t meierr; + switch (enable) { + case 0: + meierr = DSL_DEV_MEI_ERR_SUCCESS; + IFX_MEI_IRQDisable (pDev); + break; + case 1: + IFX_MEI_IRQEnable (pDev); + meierr = DSL_DEV_MEI_ERR_SUCCESS; + break; + default: + meierr = DSL_DEV_MEI_ERR_FAILURE; + break; + + } + return meierr; +} + +/** + * Get the modem status + * This function return the modem status + * + * \param pDev the device pointer + * \return 1: modem ready 0: not ready + * \ingroup Internal + */ +static int +IFX_MEI_IsModemReady (DSL_DEV_Device_t * pDev) +{ + return DSL_DEV_PRIVATE(pDev)->modem_ready; +} + +DSL_DEV_MeiError_t +DSL_BSP_AdslLedInit (DSL_DEV_Device_t * dev, + DSL_DEV_LedId_t led_number, + DSL_DEV_LedType_t type, + DSL_DEV_LedHandler_t handler) +{ +#if 0 + struct led_config_param param; + if (led_number == DSL_LED_LINK_ID && type == DSL_LED_LINK_TYPE && handler == /*DSL_LED_HD_CPU*/DSL_LED_HD_FW) { + param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE; + param.led = 0x01; + param.source = 0x01; +// bsp_led_config (¶m); + + } else if (led_number == DSL_LED_DATA_ID && type == DSL_LED_DATA_TYPE && (handler == DSL_LED_HD_FW)) { + param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE; + param.led = 0x02; + param.source = 0x02; +// bsp_led_config (¶m); + } +#endif + return DSL_DEV_MEI_ERR_SUCCESS; +}; +#if 0 +DSL_DEV_MeiError_t +DSL_BSP_AdslLedSet (DSL_DEV_Device_t * dev, DSL_DEV_LedId_t led_number, DSL_DEV_LedMode_t mode) +{ + printk(KERN_INFO "[%s %d]: mode = %#x, led_number = %d\n", __func__, __LINE__, mode, led_number); + switch (mode) { + case DSL_LED_OFF: + switch (led_number) { + case DSL_LED_LINK_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (1, 0); + bsp_led_set_data (1, 0); +#endif + break; + case DSL_LED_DATA_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (0, 0); + bsp_led_set_data (0, 0); +#endif + break; + } + break; + case DSL_LED_FLASH: + switch (led_number) { + case DSL_LED_LINK_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (1, 1); // data +#endif + break; + case DSL_LED_DATA_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (0, 1); // data +#endif + break; + } + break; + case DSL_LED_ON: + switch (led_number) { + case DSL_LED_LINK_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (1, 0); + bsp_led_set_data (1, 1); +#endif + break; + case DSL_LED_DATA_ID: +#ifdef CONFIG_BSP_LED + bsp_led_set_blink (0, 0); + bsp_led_set_data (0, 1); +#endif + break; + } + break; + } + return DSL_DEV_MEI_ERR_SUCCESS; +}; + +#endif + +/** +* Compose a message. +* This function compose a message from opcode, group, address, index, size, and data +* +* \param opcode The message opcode +* \param group The message group number +* \param address The message address. +* \param index The message index. +* \param size The number of words to read/write. +* \param data The pointer to data. +* \param CMVMSG The pointer to message buffer. +* \ingroup Internal +*/ +void +makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 *CMVMSG) +{ + memset (CMVMSG, 0, MSG_LENGTH * 2); + CMVMSG[0] = (opcode << 4) + (size & 0xf); + CMVMSG[1] = (((index == 0) ? 0 : 1) << 7) + (group & 0x7f); + CMVMSG[2] = address; + CMVMSG[3] = index; + if (opcode == H2D_CMV_WRITE) + memcpy (CMVMSG + 4, data, size * 2); + return; +} + +/** + * Send a message to ARC and read the response + * This function sends a message to arc, waits the response, and reads the responses. + * + * \param pDev the device pointer + * \param request Pointer to the request + * \param reply Wait reply or not. + * \param response Pointer to the response + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +DSL_DEV_MeiError_t +DSL_BSP_SendCMV (DSL_DEV_Device_t * pDev, u16 * request, int reply, u16 * response) // write cmv to arc, if reply needed, wait for reply +{ + DSL_DEV_MeiError_t meierror; +#if defined(BSP_PORT_RTEMS) + int delay_counter = 0; +#endif + + if (MEI_MUTEX_LOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema)) + return -ERESTARTSYS; + + DSL_DEV_PRIVATE(pDev)->cmv_reply = reply; + memset (DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, 0, + sizeof (DSL_DEV_PRIVATE(pDev)-> + CMV_RxMsg)); + DSL_DEV_PRIVATE(pDev)->arcmsgav = 0; + + meierror = IFX_MEI_MailboxWrite (pDev, request, MSG_LENGTH); + + if (meierror != DSL_DEV_MEI_ERR_SUCCESS) { + DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0; + DSL_DEV_PRIVATE(pDev)->arcmsgav = 0; + IFX_MEI_EMSG ("MailboxWrite Fail!\n"); + IFX_MEI_EMSG ("Resetting ARC...\n"); + IFX_MEI_ResetARC(pDev); + MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema); + return meierror; + } + else { + DSL_DEV_PRIVATE(pDev)->cmv_count++; + } + + if (DSL_DEV_PRIVATE(pDev)->cmv_reply == + NO_REPLY) { + MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema); + return DSL_DEV_MEI_ERR_SUCCESS; + } + +#if !defined(BSP_PORT_RTEMS) + if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0) + MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav, CMV_TIMEOUT); +#else + while (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0 && delay_counter < CMV_TIMEOUT / 5) { + MEI_WAIT (5); + delay_counter++; + } +#endif + + DSL_DEV_PRIVATE(pDev)->cmv_waiting = 0; + if (DSL_DEV_PRIVATE(pDev)->arcmsgav == 0) { //CMV_timeout + DSL_DEV_PRIVATE(pDev)->arcmsgav = 0; + IFX_MEI_EMSG ("\%s: DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT\n", + __FUNCTION__); + MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema); + return DSL_DEV_MEI_ERR_MAILBOX_TIMEOUT; + } + else { + DSL_DEV_PRIVATE(pDev)->arcmsgav = 0; + DSL_DEV_PRIVATE(pDev)-> + reply_count++; + memcpy (response, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2); + MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema); + return DSL_DEV_MEI_ERR_SUCCESS; + } + MEI_MUTEX_UNLOCK (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema); + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/** + * Reset the ARC, download boot codes, and run the ARC. + * This function resets the ARC, downloads boot codes to ARC, and runs the ARC. + * + * \param pDev the device pointer + * \return DSL_DEV_MEI_ERR_SUCCESS or DSL_DEV_MEI_ERR_FAILURE + * \ingroup Internal + */ +static DSL_DEV_MeiError_t +IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev) +{ + int nSize = 0, idx = 0; + uint32_t im0_register, im2_register; +// DSL_DEV_WinHost_Message_t m; + + if (mei_arc_swap_buff == NULL) { + mei_arc_swap_buff = + (u32 *) kmalloc (MAXSWAPSIZE * 4, GFP_KERNEL); + if (mei_arc_swap_buff == NULL) { + IFX_MEI_EMSG (">>> malloc fail for codeswap buff!!! <<<\n"); + return DSL_DEV_MEI_ERR_FAILURE; + } + IFX_MEI_DMSG("allocate %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff); + } + + DSL_DEV_PRIVATE(pDev)->img_hdr = + (ARC_IMG_HDR *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[0].address; + if ((DSL_DEV_PRIVATE(pDev)->img_hdr-> + count) * sizeof (ARC_SWP_PAGE_HDR) > SDRAM_SEGMENT_SIZE) { + IFX_MEI_EMSG ("firmware header size is bigger than 64K segment size\n"); + return DSL_DEV_MEI_ERR_FAILURE; + } + // check image size + for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) { + nSize += DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].nCopy; + } + if (nSize != + DSL_DEV_PRIVATE(pDev)->image_size) { + IFX_MEI_EMSG ("Firmware download is not completed. Please download firmware again!\n"); + return DSL_DEV_MEI_ERR_FAILURE; + } + // TODO: check crc + /// + + IFX_MEI_ResetARC (pDev); + IFX_MEI_HaltArc (pDev); + IFX_MEI_BarUpdate (pDev, DSL_DEV_PRIVATE(pDev)->nBar); + + //IFX_MEI_DMSG("Starting to meiDownloadBootCode\n"); + + IFX_MEI_DownloadBootCode (pDev); + + im0_register = (*LTQ_ICU_IM0_IER) & (1 << 20); + im2_register = (*LTQ_ICU_IM2_IER) & (1 << 20); + /* Turn off irq */ + #ifdef CONFIG_SOC_AMAZON_SE +#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL0 + 23) + disable_irq (IFXMIPS_USB_OC_INT0); +// disable_irq (IFXMIPS_USB_OC_INT2); + #elif defined(CONFIG_SOC_AR9) +#define IFXMIPS_USB_OC_INT0 (INT_NUM_IM4_IRL1 + 28) + disable_irq (IFXMIPS_USB_OC_INT0); +// disable_irq (IFXMIPS_USB_OC_INT2); + #elif defined(CONFIG_SOC_XWAY) + disable_irq (LTQ_USB_OC_INT); + #else + #error unkonwn arch + #endif + disable_irq (pDev->nIrq[IFX_DYING_GASP]); + + IFX_MEI_RunArc (pDev); + + MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000); + + #ifdef CONFIG_SOC_AMAZON_SE + MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0); +// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2); + #elif defined(CONFIG_SOC_AR9) + MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0); +// MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2); + #elif defined(CONFIG_SOC_XWAY) + MEI_MASK_AND_ACK_IRQ (LTQ_USB_OC_INT); + #else + #error unkonwn arch + #endif + MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]); + + /* Re-enable irq */ + enable_irq(pDev->nIrq[IFX_DYING_GASP]); + *LTQ_ICU_IM0_IER |= im0_register; + *LTQ_ICU_IM2_IER |= im2_register; + + if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) { + IFX_MEI_EMSG ("Modem failed to be ready!\n"); + return DSL_DEV_MEI_ERR_FAILURE; + } else { + IFX_MEI_DMSG("Modem is ready.\n"); + return DSL_DEV_MEI_ERR_SUCCESS; + } +} + +/** + * Get the page's data pointer + * This function caculats the data address from the firmware header. + * + * \param pDev the device pointer + * \param Page The page number. + * \param data Data page or program page. + * \param MaxSize The maximum size to read. + * \param Buffer Pointer to data. + * \param Dest Pointer to the destination address. + * \return The number of bytes to read. + * \ingroup Internal + */ +static int +IFX_MEI_GetPage (DSL_DEV_Device_t * pDev, u32 Page, u32 data, + u32 MaxSize, u32 * Buffer, u32 * Dest) +{ + u32 size; + u32 i; + u32 *p; + u32 idx, offset, nBar = 0; + + if (Page > DSL_DEV_PRIVATE(pDev)->img_hdr->count) + return -2; + /* + ** Get program or data size, depending on "data" flag + */ + size = (data == GET_DATA) ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_size) : + (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_size); + size &= BOOT_FLAG_MASK; // Clear boot bit! + if (size > MaxSize) + return -1; + + if (size == 0) + return 0; + /* + ** Get program or data offset, depending on "data" flag + */ + i = data ? (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].d_offset) : + (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_offset); + + /* + ** Copy data/program to buffer + */ + + idx = i / SDRAM_SEGMENT_SIZE; + offset = i % SDRAM_SEGMENT_SIZE; + p = (u32 *) ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address + offset); + + for (i = 0; i < size; i++) { + if (offset + i * 4 - (nBar * SDRAM_SEGMENT_SIZE) >= SDRAM_SEGMENT_SIZE) { + idx++; + nBar++; + p = (u32 *) ((u8 *) KSEG1ADDR ((u32)DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address)); + } + Buffer[i] = *p++; + } + + /* + ** Pass back data/program destination address + */ + *Dest = data ? (DSL_DEV_PRIVATE(pDev)-> img_hdr->page[Page].d_dest) : + (DSL_DEV_PRIVATE(pDev)->img_hdr->page[Page].p_dest); + + return size; +} + +/** + * Free the memory for ARC firmware + * + * \param pDev the device pointer + * \param type Free all memory or free the unused memory after showtime + * \ingroup Internal + */ +const char *free_str[4] = {"Invalid", "Free_Reload", "Free_Showtime", "Free_All"}; +static int +IFX_MEI_DFEMemoryFree (DSL_DEV_Device_t * pDev, int type) +{ + int idx = 0; + smmu_mem_info_t *adsl_mem_info = + DSL_DEV_PRIVATE(pDev)->adsl_mem_info; + + for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) { + if (type == FREE_ALL ||adsl_mem_info[idx].type == type) { + if (adsl_mem_info[idx].size > 0) { + IFX_MEI_DMSG ("Freeing memory %p (%s)\n", adsl_mem_info[idx].org_address, free_str[adsl_mem_info[idx].type]); + if ( idx == XDATA_REGISTER ) { + g_xdata_addr = NULL; + if ( ifx_mei_atm_showtime_exit ) + ifx_mei_atm_showtime_exit(); + } + kfree (adsl_mem_info[idx].org_address); + adsl_mem_info[idx].org_address = 0; + adsl_mem_info[idx].address = 0; + adsl_mem_info[idx].size = 0; + adsl_mem_info[idx].type = 0; + adsl_mem_info[idx].nCopy = 0; + } + } + } + + if(mei_arc_swap_buff != NULL){ + IFX_MEI_DMSG("free %dKB swap buff memory at: 0x%p\n", ksize(mei_arc_swap_buff)/1024, mei_arc_swap_buff); + kfree(mei_arc_swap_buff); + mei_arc_swap_buff=NULL; + } + + return 0; +} +static int +IFX_MEI_DFEMemoryAlloc (DSL_DEV_Device_t * pDev, long size) +{ + unsigned long mem_ptr; + char *org_mem_ptr = NULL; + int idx = 0; + long total_size = 0; + int err = 0; + smmu_mem_info_t *adsl_mem_info = + ((ifx_mei_device_private_t *) pDev->pPriv)->adsl_mem_info; +// DSL_DEV_PRIVATE(pDev)->adsl_mem_info; + int allocate_size = SDRAM_SEGMENT_SIZE; + + IFX_MEI_DMSG("image_size = %ld\n", size); + // Alloc Swap Pages + for (idx = 0; size > 0 && idx < MAX_BAR_REGISTERS; idx++) { + // skip bar15 for XDATA usage. + if (idx == XDATA_REGISTER) + continue; +#if 0 + if (size < SDRAM_SEGMENT_SIZE) { + allocate_size = size; + if (allocate_size < 1024) + allocate_size = 1024; + } +#endif + if (idx == (MAX_BAR_REGISTERS - 1)) + allocate_size = size; + else + allocate_size = SDRAM_SEGMENT_SIZE; + org_mem_ptr = kmalloc (allocate_size + 1024, GFP_KERNEL); + if (org_mem_ptr == NULL) { + IFX_MEI_EMSG ("%d: kmalloc %d bytes memory fail!\n", idx, allocate_size); + err = -ENOMEM; + goto allocate_error; + } + mem_ptr = (unsigned long) (org_mem_ptr + 1023) & ~(1024 -1); + adsl_mem_info[idx].address = (char *) mem_ptr; + adsl_mem_info[idx].org_address = org_mem_ptr; + adsl_mem_info[idx].size = allocate_size; + size -= allocate_size; + total_size += allocate_size; + } + if (size > 0) { + IFX_MEI_EMSG ("Image size is too large!\n"); + err = -EFBIG; + goto allocate_error; + } + err = idx; + return err; + + allocate_error: + IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); + return err; +} + +/** + * Program the BAR registers + * + * \param pDev the device pointer + * \param nTotalBar The number of bar to program. + * \ingroup Internal + */ +static int +IFX_MEI_BarUpdate (DSL_DEV_Device_t * pDev, int nTotalBar) +{ + int idx = 0; + smmu_mem_info_t *adsl_mem_info = + DSL_DEV_PRIVATE(pDev)->adsl_mem_info; + + for (idx = 0; idx < nTotalBar; idx++) { + //skip XDATA register + if (idx == XDATA_REGISTER) + continue; + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4, + (((uint32_t) adsl_mem_info[idx].address) & 0x0FFFFFFF)); + } + for (idx = nTotalBar; idx < MAX_BAR_REGISTERS; idx++) { + if (idx == XDATA_REGISTER) + continue; + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + idx * 4, + (((uint32_t)adsl_mem_info[nTotalBar - 1].address) & 0x0FFFFFFF)); + /* These are for /proc/danube_mei/meminfo purpose */ + adsl_mem_info[idx].address = adsl_mem_info[nTotalBar - 1].address; + adsl_mem_info[idx].org_address = adsl_mem_info[nTotalBar - 1].org_address; + adsl_mem_info[idx].size = 0; /* Prevent it from being freed */ + } + + g_xdata_addr = adsl_mem_info[XDATA_REGISTER].address; + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XMEM_BAR_BASE + XDATA_REGISTER * 4, + (((uint32_t) adsl_mem_info [XDATA_REGISTER].address) & 0x0FFFFFFF)); + // update MEI_XDATA_BASE_SH + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH, + ((unsigned long)adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF); + + return DSL_DEV_MEI_ERR_SUCCESS; +} + +/* This copies the firmware from secondary storage to 64k memory segment in SDRAM */ +DSL_DEV_MeiError_t +DSL_BSP_FWDownload (DSL_DEV_Device_t * pDev, const char *buf, + unsigned long size, long *loff, long *current_offset) +{ + ARC_IMG_HDR img_hdr_tmp; + smmu_mem_info_t *adsl_mem_info = DSL_DEV_PRIVATE(pDev)->adsl_mem_info; + + size_t nRead = 0, nCopy = 0; + char *mem_ptr; + ssize_t retval = -ENOMEM; + int idx = 0; + + IFX_MEI_DMSG("\n"); + + if (*loff == 0) { + if (size < sizeof (img_hdr_tmp)) { + IFX_MEI_EMSG ("Firmware size is too small!\n"); + return retval; + } + copy_from_user ((char *) &img_hdr_tmp, buf, sizeof (img_hdr_tmp)); + // header of image_size and crc are not included. + DSL_DEV_PRIVATE(pDev)->image_size = le32_to_cpu (img_hdr_tmp.size) + 8; + + if (DSL_DEV_PRIVATE(pDev)->image_size > 1024 * 1024) { + IFX_MEI_EMSG ("Firmware size is too large!\n"); + return retval; + } + // check if arc is halt + IFX_MEI_ResetARC (pDev); + IFX_MEI_HaltArc (pDev); + + IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); //free all + + retval = IFX_MEI_DFEMemoryAlloc (pDev, DSL_DEV_PRIVATE(pDev)->image_size); + if (retval < 0) { + IFX_MEI_EMSG ("Error: No memory space left.\n"); + goto error; + } + for (idx = 0; idx < retval; idx++) { + //skip XDATA register + if (idx == XDATA_REGISTER) + continue; + if (idx * SDRAM_SEGMENT_SIZE < le32_to_cpu (img_hdr_tmp.page[0].p_offset)) + adsl_mem_info[idx].type = FREE_RELOAD; + else + adsl_mem_info[idx].type = FREE_SHOWTIME; + } + DSL_DEV_PRIVATE(pDev)->nBar = retval; + + DSL_DEV_PRIVATE(pDev)->img_hdr = + (ARC_IMG_HDR *) adsl_mem_info[0].address; + + adsl_mem_info[XDATA_REGISTER].org_address = kmalloc (SDRAM_SEGMENT_SIZE + 1024, GFP_KERNEL); + adsl_mem_info[XDATA_REGISTER].address = + (char *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER].org_address + 1023) & 0xFFFFFC00); + + adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE; + + if (adsl_mem_info[XDATA_REGISTER].address == NULL) { + IFX_MEI_EMSG ("kmalloc memory fail!\n"); + retval = -ENOMEM; + goto error; + } + adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD; + IFX_MEI_DMSG("-> IFX_MEI_BarUpdate()\n"); + IFX_MEI_BarUpdate (pDev, (DSL_DEV_PRIVATE(pDev)->nBar)); + } + else if (DSL_DEV_PRIVATE(pDev)-> image_size == 0) { + IFX_MEI_EMSG ("Error: Firmware size=0! \n"); + goto error; + } + + nRead = 0; + while (nRead < size) { + long offset = ((long) (*loff) + nRead) % SDRAM_SEGMENT_SIZE; + idx = (((long) (*loff)) + nRead) / SDRAM_SEGMENT_SIZE; + mem_ptr = (char *) KSEG1ADDR ((unsigned long) (adsl_mem_info[idx].address) + offset); + if ((size - nRead + offset) > SDRAM_SEGMENT_SIZE) + nCopy = SDRAM_SEGMENT_SIZE - offset; + else + nCopy = size - nRead; + copy_from_user (mem_ptr, buf + nRead, nCopy); + for (offset = 0; offset < (nCopy / 4); offset++) { + ((unsigned long *) mem_ptr)[offset] = le32_to_cpu (((unsigned long *) mem_ptr)[offset]); + } + nRead += nCopy; + adsl_mem_info[idx].nCopy += nCopy; + } + + *loff += size; + *current_offset = size; + return DSL_DEV_MEI_ERR_SUCCESS; +error: + IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); + return DSL_DEV_MEI_ERR_FAILURE; +} +/* + * Register a callback event. + * Return: + * -1 if the event already has a callback function registered. + * 0 success + */ +int DSL_BSP_EventCBRegister(DSL_BSP_EventCallBack_t *p) +{ + if (!p) { + IFX_MEI_EMSG("Invalid parameter!\n"); + return -EINVAL; + } + if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) { + IFX_MEI_EMSG("Invalid Event %d\n", p->event); + return -EINVAL; + } + if (dsl_bsp_event_callback[p->event].function) { + IFX_MEI_EMSG("Event %d already has a callback function registered!\n", p->event); + return -1; + } else { + dsl_bsp_event_callback[p->event].function = p->function; + dsl_bsp_event_callback[p->event].event = p->event; + dsl_bsp_event_callback[p->event].pData = p->pData; + } + return 0; +} +int DSL_BSP_EventCBUnregister(DSL_BSP_EventCallBack_t *p) +{ + if (!p) { + IFX_MEI_EMSG("Invalid parameter!\n"); + return -EINVAL; + } + if (p->event > DSL_BSP_CB_LAST || p->event < DSL_BSP_CB_FIRST) { + IFX_MEI_EMSG("Invalid Event %d\n", p->event); + return -EINVAL; + } + if (dsl_bsp_event_callback[p->event].function) { + IFX_MEI_EMSG("Unregistering Event %d...\n", p->event); + dsl_bsp_event_callback[p->event].function = NULL; + dsl_bsp_event_callback[p->event].pData = NULL; + } else { + IFX_MEI_EMSG("Event %d is not registered!\n", p->event); + return -1; + } + return 0; +} + +/** + * MEI Dying Gasp interrupt handler + * + * \param int1 + * \param void0 + * \param regs Pointer to the structure of danube mips registers + * \ingroup Internal + */ +static irqreturn_t IFX_MEI_Dying_Gasp_IrqHandle (int int1, void *void0) +{ + DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0; + DSL_BSP_CB_Type_t event; + + if (pDev == NULL) + IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n"); + +#ifndef CONFIG_SMP + disable_irq (pDev->nIrq[IFX_DYING_GASP]); +#else + disable_irq_nosync(pDev->nIrq[IFX_DYING_GASP]); +#endif + event = DSL_BSP_CB_DYING_GASP; + + if (dsl_bsp_event_callback[event].function) + (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData); + +#ifdef CONFIG_USE_EMULATOR + IFX_MEI_EMSG("Dying Gasp! Shutting Down... (Work around for Amazon-S Venus emulator)\n"); +#else + IFX_MEI_EMSG("Dying Gasp! Shutting Down...\n"); +// kill_proc (1, SIGINT, 1); /* Ask init to reboot us */ +#endif + return IRQ_HANDLED; +} + +extern void ifx_usb_enable_afe_oc(void); + +/** + * MEI interrupt handler + * + * \param int1 + * \param void0 + * \param regs Pointer to the structure of danube mips registers + * \ingroup Internal + */ +static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0) +{ + u32 scratch; + DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0; +#if defined(CONFIG_LTQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST) + dfe_loopback_irq_handler (pDev); + return IRQ_HANDLED; +#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK + DSL_BSP_CB_Type_t event; + + if (pDev == NULL) + IFX_MEI_EMSG("Error: Got Interrupt but pDev is NULL!!!!\n"); + + IFX_MEI_DebugRead (pDev, ARC_MEI_MAILBOXR, &scratch, 1); + if (scratch & OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK) { + IFX_MEI_EMSG("Receive Code Swap Request interrupt!!!\n"); + return IRQ_HANDLED; + } + else if (scratch & OMB_CLEAREOC_INTERRUPT_CODE) { + // clear eoc message interrupt + IFX_MEI_DMSG("OMB_CLEAREOC_INTERRUPT_CODE\n"); + event = DSL_BSP_CB_CEOC_IRQ; + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV); + if (dsl_bsp_event_callback[event].function) + (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData); + } else if (scratch & OMB_REBOOT_INTERRUPT_CODE) { + // Reboot + IFX_MEI_DMSG("OMB_REBOOT_INTERRUPT_CODE\n"); + event = DSL_BSP_CB_FIRMWARE_REBOOT; + + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_ARC2ME_STAT, ARC_TO_MEI_MSGAV); + + if (dsl_bsp_event_callback[event].function) + (*dsl_bsp_event_callback[event].function)(pDev, event, dsl_bsp_event_callback[event].pData); + } else { // normal message + IFX_MEI_MailboxRead (pDev, DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH); + if (DSL_DEV_PRIVATE(pDev)-> cmv_waiting == 1) { + DSL_DEV_PRIVATE(pDev)-> arcmsgav = 1; + DSL_DEV_PRIVATE(pDev)-> cmv_waiting = 0; +#if !defined(BSP_PORT_RTEMS) + MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav); +#endif + } + else { + DSL_DEV_PRIVATE(pDev)-> modem_ready_cnt++; + memcpy ((char *) DSL_DEV_PRIVATE(pDev)->Recent_indicator, + (char *) DSL_DEV_PRIVATE(pDev)->CMV_RxMsg, MSG_LENGTH * 2); + if (((DSL_DEV_PRIVATE(pDev)->CMV_RxMsg[0] & 0xff0) >> 4) == D2H_AUTONOMOUS_MODEM_READY_MSG) { + //check ARC ready message + IFX_MEI_DMSG ("Got MODEM_READY_MSG\n"); + DSL_DEV_PRIVATE(pDev)->modem_ready = 1; + MEI_WAKEUP_EVENT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready); + } + } + } + + return IRQ_HANDLED; +} + +int +DSL_BSP_ATMLedCBRegister (int (*ifx_adsl_ledcallback) (void)) +{ + g_adsl_ledcallback = ifx_adsl_ledcallback; + return 0; +} + +int +DSL_BSP_ATMLedCBUnregister (int (*ifx_adsl_ledcallback) (void)) +{ + g_adsl_ledcallback = adsl_dummy_ledcallback; + return 0; +} + +#if 0 +int +DSL_BSP_EventCBRegister (int (*ifx_adsl_callback) + (DSL_BSP_CB_Event_t * param)) +{ + int error = 0; + + if (DSL_EventCB == NULL) { + DSL_EventCB = ifx_adsl_callback; + } + else { + error = -EIO; + } + return error; +} + +int +DSL_BSP_EventCBUnregister (int (*ifx_adsl_callback) + (DSL_BSP_CB_Event_t * param)) +{ + int error = 0; + + if (DSL_EventCB == ifx_adsl_callback) { + DSL_EventCB = NULL; + } + else { + error = -EIO; + } + return error; +} + +static int +DSL_BSP_GetEventCB (int (**ifx_adsl_callback) + (DSL_BSP_CB_Event_t * param)) +{ + *ifx_adsl_callback = DSL_EventCB; + return 0; +} +#endif + +#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK +#define mte_reg_base (0x4800*4+0x20000) + +/* Iridia Registers Address Constants */ +#define MTE_Reg(r) (int)(mte_reg_base + (r*4)) + +#define IT_AMODE MTE_Reg(0x0004) + +#define TIMER_DELAY (1024) +#define BC0_BYTES (32) +#define BC1_BYTES (30) +#define NUM_MB (12) +#define TIMEOUT_VALUE 2000 + +static void +BFMWait (u32 cycle) +{ + u32 i; + for (i = 0; i < cycle; i++); +} + +static void +WriteRegLong (u32 addr, u32 data) +{ + //*((volatile u32 *)(addr)) = data; + IFX_MEI_WRITE_REGISTER_L (data, addr); +} + +static u32 +ReadRegLong (u32 addr) +{ + // u32 rd_val; + //rd_val = *((volatile u32 *)(addr)); + // return rd_val; + return IFX_MEI_READ_REGISTER_L (addr); +} + +/* This routine writes the mailbox with the data in an input array */ +static void +WriteMbox (u32 * mboxarray, u32 size) +{ + IFX_MEI_DebugWrite (&dsl_devices[0], IMBOX_BASE, mboxarray, size); + IFX_MEI_DMSG("write to %X\n", IMBOX_BASE); + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ME2ARC_INT, MEI_TO_ARC_MSGAV); +} + +/* This routine reads the output mailbox and places the results into an array */ +static void +ReadMbox (u32 * mboxarray, u32 size) +{ + IFX_MEI_DebugRead (&dsl_devices[0], OMBOX_BASE, mboxarray, size); + IFX_MEI_DMSG("read from %X\n", OMBOX_BASE); +} + +static void +MEIWriteARCValue (u32 address, u32 value) +{ + u32 i, check = 0; + + /* Write address register */ + IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + LTQ_MEI_BASE_ADDR); + + /* Write data register */ + IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LTQ_MEI_BASE_ADDR); + + /* wait until complete - timeout at 40 */ + for (i = 0; i < 40; i++) { + check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR); + + if ((check & ARC_TO_MEI_DBG_DONE)) + break; + } + /* clear the flag */ + IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR); +} + +void +arc_code_page_download (uint32_t arc_code_length, uint32_t * start_address) +{ + int count; + + IFX_MEI_DMSG("try to download pages,size=%d\n", arc_code_length); + IFX_MEI_ControlModeSet (&dsl_devices[0], MEI_MASTER_MODE); + IFX_MEI_HaltArc (&dsl_devices[0]); + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_AD, 0); + for (count = 0; count < arc_code_length; count++) { + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_DX_DATA, + *(start_address + count)); + } + IFX_MEI_ControlModeSet (&dsl_devices[0], JTAG_MASTER_MODE); +} +static int +load_jump_table (unsigned long addr) +{ + int i; + uint32_t addr_le, addr_be; + uint32_t jump_table[32]; + + for (i = 0; i < 16; i++) { + addr_le = i * 8 + addr; + addr_be = ((addr_le >> 16) & 0xffff); + addr_be |= ((addr_le & 0xffff) << 16); + jump_table[i * 2 + 0] = 0x0f802020; + jump_table[i * 2 + 1] = addr_be; + //printk("jt %X %08X %08X\n",i,jump_table[i*2+0],jump_table[i*2+1]); + } + arc_code_page_download (32, &jump_table[0]); +return 0; +} + +int got_int = 0; + +void +dfe_loopback_irq_handler (DSL_DEV_Device_t *pDev) +{ + uint32_t rd_mbox[10]; + + memset (&rd_mbox[0], 0, 10 * 4); + ReadMbox (&rd_mbox[0], 6); + if (rd_mbox[0] == 0x0) { + FX_MEI_DMSG("Get ARC_ACK\n"); + got_int = 1; + } + else if (rd_mbox[0] == 0x5) { + IFX_MEI_DMSG("Get ARC_BUSY\n"); + got_int = 2; + } + else if (rd_mbox[0] == 0x3) { + IFX_MEI_DMSG("Get ARC_EDONE\n"); + if (rd_mbox[1] == 0x0) { + got_int = 3; + IFX_MEI_DMSG("Get E_MEMTEST\n"); + if (rd_mbox[2] != 0x1) { + got_int = 4; + IFX_MEI_DMSG("Get Result %X\n", rd_mbox[2]); + } + } + } + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_STAT, + ARC_TO_MEI_DBG_DONE); + MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]); + disable_irq (pDev->nIrq[IFX_DFEIR]); + //got_int = 1; + return; +} + +static void +wait_mem_test_result (void) +{ + uint32_t mbox[5]; + mbox[0] = 0; + + IFX_MEI_DMSG("Waiting Starting\n"); + while (mbox[0] == 0) { + ReadMbox (&mbox[0], 5); + } + IFX_MEI_DMSG("Try to get mem test result.\n"); + ReadMbox (&mbox[0], 5); + if (mbox[0] == 0xA) { + IFX_MEI_DMSG("Success.\n"); + } + else if (mbox[0] == 0xA) { + IFX_MEI_EMSG("Fail,address %X,except data %X,receive data %X\n", + mbox[1], mbox[2], mbox[3]); + } + else { + IFX_MEI_EMSG("Fail\n"); + } +} + +static int +arc_ping_testing (DSL_DEV_Device_t *pDev) +{ +#define MEI_PING 0x00000001 + uint32_t wr_mbox[10], rd_mbox[10]; + int i; + + for (i = 0; i < 10; i++) { + wr_mbox[i] = 0; + rd_mbox[i] = 0; + } + + FX_MEI_DMSG("send ping msg\n"); + wr_mbox[0] = MEI_PING; + WriteMbox (&wr_mbox[0], 10); + + while (got_int == 0) { + MEI_WAIT (100); + } + + IFX_MEI_DMSG("send start event\n"); + got_int = 0; + + wr_mbox[0] = 0x4; + wr_mbox[1] = 0; + wr_mbox[2] = 0; + wr_mbox[3] = (uint32_t) 0xf5acc307e; + wr_mbox[4] = 5; + wr_mbox[5] = 2; + wr_mbox[6] = 0x1c000; + wr_mbox[7] = 64; + wr_mbox[8] = 0; + wr_mbox[9] = 0; + WriteMbox (&wr_mbox[0], 10); + DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]); + //printk("IFX_MEI_MailboxWrite ret=%d\n",i); + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], + (u32) ME_ME2ARC_INT, + MEI_TO_ARC_MSGAV); + IFX_MEI_DMSG("sleeping\n"); + while (1) { + if (got_int > 0) { + + if (got_int > 3) + IFX_MEI_DMSG("got_int >>>> 3\n"); + else + IFX_MEI_DMSG("got int = %d\n", got_int); + got_int = 0; + //schedule(); + DSL_ENABLE_IRQ (pDev->nIrq[IFX_DFEIR]); + } + //mbox_read(&rd_mbox[0],6); + MEI_WAIT (100); + } + return 0; +} + +static DSL_DEV_MeiError_t +DFE_Loopback_Test (void) +{ + int i = 0; + u32 arc_debug_data = 0, temp; + DSL_DEV_Device_t *pDev = &dsl_devices[0]; + uint32_t wr_mbox[10]; + + IFX_MEI_ResetARC (pDev); + // start the clock + arc_debug_data = ACL_CLK_MODE_ENABLE; + IFX_MEI_DebugWrite (pDev, CRI_CCR0, &arc_debug_data, 1); + +#if defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK) + // WriteARCreg(AUX_XMEM_LTEST,0); + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); +#define AUX_XMEM_LTEST 0x128 + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XMEM_LTEST, 0); + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + // WriteARCreg(AUX_XDMA_GAP,0); + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); +#define AUX_XDMA_GAP 0x114 + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, AUX_XDMA_GAP, 0); + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); + temp = 0; + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, + (u32) ME_XDATA_BASE_SH + LTQ_MEI_BASE_ADDR, temp); + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16); + if (i >= 0) { + int idx; + + for (idx = 0; idx < i; idx++) { + DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD; + IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff), + LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4); + IFX_MEI_DMSG("bar%d(%X)=%X\n", idx, + LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + + idx * 4, (((uint32_t) + ((ifx_mei_device_private_t *) + pDev->pPriv)->adsl_mem_info[idx]. + address) & 0x0fffffff)); + memset ((u8 *) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address, 0, SDRAM_SEGMENT_SIZE); + } + + IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_XDATA_BASE_SH, + ((unsigned long) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[XDATA_REGISTER].address) & 0x0FFFFFFF); + } + else { + IFX_MEI_EMSG ("cannot load image: no memory\n"); + return DSL_DEV_MEI_ERR_FAILURE; + } + //WriteARCreg(AUX_IC_CTRL,2); + IFX_MEI_DMSG("Setting MEI_MASTER_MODE..\n"); + IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE); +#define AUX_IC_CTRL 0x11 + _IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK, + AUX_IC_CTRL, 2); + IFX_MEI_DMSG("Setting JTAG_MASTER_MODE..\n"); + IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE); + + IFX_MEI_DMSG("Halting ARC...\n"); + IFX_MEI_HaltArc (&dsl_devices[0]); + +#ifdef DFE_PING_TEST + + IFX_MEI_DMSG("ping test image size=%d\n", sizeof (arc_ahb_access_code)); + memcpy ((u8 *) (DSL_DEV_PRIVATE(pDev)-> + adsl_mem_info[0].address + 0x1004), + &arc_ahb_access_code[0], sizeof (arc_ahb_access_code)); + load_jump_table (0x80000 + 0x1004); + +#endif //DFE_PING_TEST + + IFX_MEI_DMSG("ARC ping test code download complete\n"); +#endif //defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK) +#ifdef DFE_MEM_TEST + IFX_MEI_LongWordWriteOffset (&dsl_devices[0], (u32) ME_ARC2ME_MASK, MSGAV_EN); + + arc_code_page_download (1537, &code_array[0]); + IFX_MEI_DMSG("ARC mem test code download complete\n"); +#endif //DFE_MEM_TEST +#ifdef DFE_ATM_LOOPBACK + arc_debug_data = 0xf; + arc_code_page_download (sizeof(code_array) / sizeof(*code_array), &code_array[0]); + wr_mbox[0] = 0; //TIMER_DELAY - org: 1024 + wr_mbox[1] = 0; //TXFB_START0 + wr_mbox[2] = 0x7f; //TXFB_END0 - org: 49 + wr_mbox[3] = 0x80; //TXFB_START1 - org: 80 + wr_mbox[4] = 0xff; //TXFB_END1 - org: 109 + wr_mbox[5] = 0x100; //RXFB_START0 - org: 0 + wr_mbox[6] = 0x17f; //RXFB_END0 - org: 49 + wr_mbox[7] = 0x180; //RXFB_START1 - org: 256 + wr_mbox[8] = 0x1ff; //RXFB_END1 - org: 315 + WriteMbox (&wr_mbox[0], 9); + // Start Iridia IT_AMODE (in dmp access) why is it required? + IFX_MEI_DebugWrite (&dsl_devices[0], 0x32010, &arc_debug_data, 1); +#endif //DFE_ATM_LOOPBACK + IFX_MEI_IRQEnable (pDev); + IFX_MEI_DMSG("run ARC...\n"); + IFX_MEI_RunArc (&dsl_devices[0]); + +#ifdef DFE_PING_TEST + arc_ping_testing (pDev); +#endif //DFE_PING_TEST +#ifdef DFE_MEM_TEST + wait_mem_test_result (); +#endif //DFE_MEM_TEST + + IFX_MEI_DFEMemoryFree (pDev, FREE_ALL); + return DSL_DEV_MEI_ERR_SUCCESS; +} + +#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK + +static int +IFX_MEI_InitDevNode (int num) +{ + if (num == 0) { + if ((dev_major = register_chrdev (dev_major, IFX_MEI_DEVNAME, &bsp_mei_operations)) < 0) { + IFX_MEI_EMSG ("register_chrdev(%d %s) failed!\n", dev_major, IFX_MEI_DEVNAME); + return -ENODEV; + } + } + return 0; +} + +static int +IFX_MEI_CleanUpDevNode (int num) +{ + if (num == 0) + unregister_chrdev (dev_major, MEI_DIRNAME); + return 0; +} + +static int +IFX_MEI_InitDevice (int num) +{ + DSL_DEV_Device_t *pDev; + u32 temp; + pDev = &dsl_devices[num]; + if (pDev == NULL) + return -ENOMEM; + pDev->pPriv = &sDanube_Mei_Private[num]; + memset (pDev->pPriv, 0, sizeof (ifx_mei_device_private_t)); + + memset (&DSL_DEV_PRIVATE(pDev)-> + adsl_mem_info[0], 0, + sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS); + + if (num == 0) { + pDev->nIrq[IFX_DFEIR] = LTQ_MEI_INT; + pDev->nIrq[IFX_DYING_GASP] = LTQ_MEI_DYING_GASP_INT; + pDev->base_address = KSEG1 + LTQ_MEI_BASE_ADDR; + + /* Power up MEI */ +#ifdef CONFIG_LANTIQ_AMAZON_SE + *LTQ_PMU_PWDCR &= ~(1 << 9); // enable dsl + *LTQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base +#else + temp = ltq_r32(LTQ_PMU_PWDCR); + temp &= 0xffff7dbe; + ltq_w32(temp, LTQ_PMU_PWDCR); +#endif + } + pDev->nInUse = 0; + DSL_DEV_PRIVATE(pDev)->modem_ready = 0; + DSL_DEV_PRIVATE(pDev)->arcmsgav = 0; + + MEI_INIT_WAKELIST ("arcq", DSL_DEV_PRIVATE(pDev)->wait_queue_arcmsgav); // for ARCMSGAV + MEI_INIT_WAKELIST ("arcr", DSL_DEV_PRIVATE(pDev)->wait_queue_modemready); // for arc modem ready + + MEI_MUTEX_INIT (DSL_DEV_PRIVATE(pDev)->mei_cmv_sema, 1); // semaphore initialization, mutex +#if 0 + MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DFEIR]); + MEI_MASK_AND_ACK_IRQ (pDev->nIrq[IFX_DYING_GASP]); +#endif + if (request_irq (pDev->nIrq[IFX_DFEIR], IFX_MEI_IrqHandle, 0, "DFEIR", pDev) != 0) { + IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DFEIR]); + return -1; + } + /*if (request_irq (pDev->nIrq[IFX_DYING_GASP], IFX_MEI_Dying_Gasp_IrqHandle, 0, "DYING_GASP", pDev) != 0) { + IFX_MEI_EMSG ("request_irq %d failed!\n", pDev->nIrq[IFX_DYING_GASP]); + return -1; + }*/ +// IFX_MEI_DMSG("Device %d initialized. IER %#x\n", num, bsp_get_irq_ier(pDev->nIrq[IFX_DYING_GASP])); + return 0; +} + +static int +IFX_MEI_ExitDevice (int num) +{ + DSL_DEV_Device_t *pDev; + pDev = &dsl_devices[num]; + + if (pDev == NULL) + return -EIO; + + disable_irq (pDev->nIrq[IFX_DFEIR]); + disable_irq (pDev->nIrq[IFX_DYING_GASP]); + + free_irq(pDev->nIrq[IFX_DFEIR], pDev); + free_irq(pDev->nIrq[IFX_DYING_GASP], pDev); + + return 0; +} + +static DSL_DEV_Device_t * +IFX_BSP_HandleGet (int maj, int num) +{ + if (num > BSP_MAX_DEVICES) + return NULL; + return &dsl_devices[num]; +} + +DSL_DEV_Device_t * +DSL_BSP_DriverHandleGet (int maj, int num) +{ + DSL_DEV_Device_t *pDev; + + if (num > BSP_MAX_DEVICES) + return NULL; + + pDev = &dsl_devices[num]; + if (!try_module_get(pDev->owner)) + return NULL; + + pDev->nInUse++; + return pDev; +} + +int +DSL_BSP_DriverHandleDelete (DSL_DEV_Device_t * nHandle) +{ + DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) nHandle; + if (pDev->nInUse) + pDev->nInUse--; + module_put(pDev->owner); + return 0; +} + +static int +IFX_MEI_Open (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil) +{ + int maj = MAJOR (ino->i_rdev); + int num = MINOR (ino->i_rdev); + + DSL_DEV_Device_t *pDev = NULL; + if ((pDev = DSL_BSP_DriverHandleGet (maj, num)) == NULL) { + IFX_MEI_EMSG("open(%d:%d) fail!\n", maj, num); + return -EIO; + } + fil->private_data = pDev; + return 0; +} + +static int +IFX_MEI_Release (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil) +{ + //int maj = MAJOR(ino->i_rdev); + int num = MINOR (ino->i_rdev); + DSL_DEV_Device_t *pDev; + + pDev = &dsl_devices[num]; + if (pDev == NULL) + return -EIO; + DSL_BSP_DriverHandleDelete (pDev); + return 0; +} + +/** + * Callback function for linux userspace program writing + */ +static ssize_t +IFX_MEI_Write (DSL_DRV_file_t * filp, const char *buf, size_t size, loff_t * loff) +{ + DSL_DEV_MeiError_t mei_error = DSL_DEV_MEI_ERR_FAILURE; + long offset = 0; + DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) filp->private_data; + + if (pDev == NULL) + return -EIO; + + mei_error = + DSL_BSP_FWDownload (pDev, buf, size, (long *) loff, &offset); + + if (mei_error == DSL_DEV_MEI_ERR_FAILURE) + return -EIO; + return (ssize_t) offset; +} + +/** + * Callback function for linux userspace program ioctling + */ +static int +IFX_MEI_IoctlCopyFrom (int from_kernel, char *dest, char *from, int size) +{ + int ret = 0; + + if (!from_kernel) + ret = copy_from_user ((char *) dest, (char *) from, size); + else + ret = (int)memcpy ((char *) dest, (char *) from, size); + return ret; +} + +static int +IFX_MEI_IoctlCopyTo (int from_kernel, char *dest, char *from, int size) +{ + int ret = 0; + + if (!from_kernel) + ret = copy_to_user ((char *) dest, (char *) from, size); + else + ret = (int)memcpy ((char *) dest, (char *) from, size); + return ret; +} + +static int +IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command, unsigned long lon) +{ + int i = 0; + int meierr = DSL_DEV_MEI_ERR_SUCCESS; + u32 base_address = LTQ_MEI_BASE_ADDR; + DSL_DEV_WinHost_Message_t winhost_msg, m; + DSL_DEV_MeiDebug_t debugrdwr; + DSL_DEV_MeiReg_t regrdwr; + + switch (command) { + + case DSL_FIO_BSP_CMV_WINHOST: + IFX_MEI_IoctlCopyFrom (from_kernel, (char *) winhost_msg.msg.TxMessage, + (char *) lon, MSG_LENGTH * 2); + + if ((meierr = DSL_BSP_SendCMV (pDev, winhost_msg.msg.TxMessage, YES_REPLY, + winhost_msg.msg.RxMessage)) != DSL_DEV_MEI_ERR_SUCCESS) { + IFX_MEI_EMSG ("WINHOST CMV fail :TxMessage:%X %X %X %X, RxMessage:%X %X %X %X %X\n", + winhost_msg.msg.TxMessage[0], winhost_msg.msg.TxMessage[1], winhost_msg.msg.TxMessage[2], winhost_msg.msg.TxMessage[3], + winhost_msg.msg.RxMessage[0], winhost_msg.msg.RxMessage[1], winhost_msg.msg.RxMessage[2], winhost_msg.msg.RxMessage[3], + winhost_msg.msg.RxMessage[4]); + meierr = DSL_DEV_MEI_ERR_FAILURE; + } + else { + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, + (char *) winhost_msg.msg.RxMessage, + MSG_LENGTH * 2); + } + break; + + case DSL_FIO_BSP_CMV_READ: + IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (®rdwr), + (char *) lon, sizeof (DSL_DEV_MeiReg_t)); + + IFX_MEI_LongWordRead ((u32) regrdwr.iAddress, + (u32 *) & (regrdwr.iData)); + + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, + (char *) (®rdwr), + sizeof (DSL_DEV_MeiReg_t)); + + break; + + case DSL_FIO_BSP_CMV_WRITE: + IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (®rdwr), + (char *) lon, sizeof (DSL_DEV_MeiReg_t)); + + IFX_MEI_LongWordWrite ((u32) regrdwr.iAddress, + regrdwr.iData); + break; + + case DSL_FIO_BSP_GET_BASE_ADDRESS: + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, + (char *) (&base_address), + sizeof (base_address)); + break; + + case DSL_FIO_BSP_IS_MODEM_READY: + i = IFX_MEI_IsModemReady (pDev); + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, + (char *) (&i), sizeof (int)); + meierr = DSL_DEV_MEI_ERR_SUCCESS; + break; + case DSL_FIO_BSP_RESET: + case DSL_FIO_BSP_REBOOT: + meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RESET); + meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT); + break; + + case DSL_FIO_BSP_HALT: + meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_HALT); + break; + + case DSL_FIO_BSP_RUN: + meierr = IFX_MEI_CpuModeSet (pDev, DSL_CPU_RUN); + break; + case DSL_FIO_BSP_BOOTDOWNLOAD: + meierr = IFX_MEI_DownloadBootCode (pDev); + break; + case DSL_FIO_BSP_JTAG_ENABLE: + meierr = IFX_MEI_ArcJtagEnable (pDev, 1); + break; + + case DSL_FIO_BSP_REMOTE: + IFX_MEI_IoctlCopyFrom (from_kernel, (char *) (&i), + (char *) lon, sizeof (int)); + + meierr = IFX_MEI_AdslMailboxIRQEnable (pDev, i); + break; + + case DSL_FIO_BSP_DSL_START: + IFX_MEI_DMSG("DSL_FIO_BSP_DSL_START\n"); + if ((meierr = IFX_MEI_RunAdslModem (pDev)) != DSL_DEV_MEI_ERR_SUCCESS) { + IFX_MEI_EMSG ("IFX_MEI_RunAdslModem() error..."); + meierr = DSL_DEV_MEI_ERR_FAILURE; + } + break; + + case DSL_FIO_BSP_DEBUG_READ: + case DSL_FIO_BSP_DEBUG_WRITE: + IFX_MEI_IoctlCopyFrom (from_kernel, + (char *) (&debugrdwr), + (char *) lon, + sizeof (debugrdwr)); + + if (command == DSL_FIO_BSP_DEBUG_READ) + meierr = DSL_BSP_MemoryDebugAccess (pDev, + DSL_BSP_MEMORY_READ, + debugrdwr. + iAddress, + debugrdwr. + buffer, + debugrdwr. + iCount); + else + meierr = DSL_BSP_MemoryDebugAccess (pDev, + DSL_BSP_MEMORY_WRITE, + debugrdwr. + iAddress, + debugrdwr. + buffer, + debugrdwr. + iCount); + + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&debugrdwr), sizeof (debugrdwr)); + break; + case DSL_FIO_BSP_GET_VERSION: + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t)); + break; + +#define LTQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) + case DSL_FIO_BSP_GET_CHIP_INFO: + bsp_chip_info.major = 1; + bsp_chip_info.minor = LTQ_MPS_CHIPID_VERSION_GET(*LTQ_MPS_CHIPID); + IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t)); + meierr = DSL_DEV_MEI_ERR_SUCCESS; + break; + + case DSL_FIO_BSP_FREE_RESOURCE: + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_STAT, 4, 0, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) { + meierr = DSL_DEV_MEI_ERR_FAILURE; + return -EIO; + } + IFX_MEI_DMSG("RxMessage[4] = %#x\n", m.msg.RxMessage[4]); + if (!(m.msg.RxMessage[4] & DSL_DEV_STAT_CODESWAP_COMPLETE)) { + meierr = DSL_DEV_MEI_ERR_FAILURE; + return -EAGAIN; + } + IFX_MEI_DMSG("Freeing all memories marked FREE_SHOWTIME\n"); + IFX_MEI_DFEMemoryFree (pDev, FREE_SHOWTIME); + meierr = DSL_DEV_MEI_ERR_SUCCESS; + break; +#ifdef CONFIG_IFXMIPS_AMAZON_SE + case DSL_FIO_ARC_MUX_TEST: + AMAZON_SE_MEI_ARC_MUX_Test(); + break; +#endif + default: +// IFX_MEI_EMSG("Invalid IOCTL command: %d\n"); + break; + } + return meierr; +} + +#ifdef CONFIG_IFXMIPS_AMAZON_SE +void AMAZON_SE_MEI_ARC_MUX_Test(void) +{ + u32 *p, i; + *LTQ_RCU_RST |= LTQ_RCU_RST_REQ_MUX_ARC; + + p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE); + IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p); + for (i = 0; i < IRAM0_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + + p = (u32*)(DFE_LDST_BASE_ADDR + IRAM1_BASE); + IFX_MEI_EMSG("Writing to IRAM1(%p)...\n", p); + for (i = 0; i < IRAM1_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + + p = (u32*)(DFE_LDST_BASE_ADDR + BRAM_BASE); + IFX_MEI_EMSG("Writing to BRAM(%p)...\n", p); + for (i = 0; i < BRAM_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + + p = (u32*)(DFE_LDST_BASE_ADDR + XRAM_BASE); + IFX_MEI_EMSG("Writing to XRAM(%p)...\n", p); + for (i = 0; i < XRAM_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + + p = (u32*)(DFE_LDST_BASE_ADDR + YRAM_BASE); + IFX_MEI_EMSG("Writing to YRAM(%p)...\n", p); + for (i = 0; i < YRAM_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + + p = (u32*)(DFE_LDST_BASE_ADDR + EXT_MEM_BASE); + IFX_MEI_EMSG("Writing to EXT_MEM(%p)...\n", p); + for (i = 0; i < EXT_MEM_SIZE/sizeof(u32); i++, p++) { + *p = 0xdeadbeef; + if (*p != 0xdeadbeef) + IFX_MEI_EMSG("%p: %#x\n", p, *p); + } + *LTQ_RCU_RST &= ~LTQ_RCU_RST_REQ_MUX_ARC; +} +#endif +int +DSL_BSP_KernelIoctls (DSL_DEV_Device_t * pDev, unsigned int command, + unsigned long lon) +{ + int error = 0; + + error = IFX_MEI_Ioctls (pDev, 1, command, lon); + return error; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) +static int +IFX_MEI_UserIoctls (DSL_DRV_inode_t * ino, DSL_DRV_file_t * fil, + unsigned int command, unsigned long lon) +#else +static int +IFX_MEI_UserIoctls (DSL_DRV_file_t * fil, + unsigned int command, unsigned long lon) +#endif +{ + int error = 0; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + int maj = MAJOR (ino->i_rdev); + int num = MINOR (ino->i_rdev); +#endif + DSL_DEV_Device_t *pDev; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + pDev = IFX_BSP_HandleGet (maj, num); +#else + pDev = IFX_BSP_HandleGet (0, 0); +#endif + if (pDev == NULL) + return -EIO; + + error = IFX_MEI_Ioctls (pDev, 0, command, lon); + return error; +} + +#ifdef CONFIG_PROC_FS +/* + * Register a callback function for linux proc filesystem + */ +static int +IFX_MEI_InitProcFS (int num) +{ + struct proc_dir_entry *entry; + int i ; + DSL_DEV_Device_t *pDev; + reg_entry_t regs_temp[PROC_ITEMS] = { + /* flag, name, description } */ + {NULL, "arcmsgav", "arc to mei message ", 0}, + {NULL, "cmv_reply", "cmv needs reply", 0}, + {NULL, "cmv_waiting", "waiting for cmv reply from arc", 0}, + {NULL, "modem_ready_cnt", "ARC to MEI indicator count", 0}, + {NULL, "cmv_count", "MEI to ARC CMVs", 0}, + {NULL, "reply_count", "ARC to MEI Reply", 0}, + {NULL, "Recent_indicator", "most recent indicator", 0}, + {NULL, "fw_version", "Firmware Version", 0}, + {NULL, "fw_date", "Firmware Date", 0}, + {NULL, "meminfo", "Memory Allocation Information", 0}, + {NULL, "version", "MEI version information", 0}, + }; + + pDev = &dsl_devices[num]; + if (pDev == NULL) + return -ENOMEM; + + regs_temp[0].flag = &(DSL_DEV_PRIVATE(pDev)->arcmsgav); + regs_temp[1].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_reply); + regs_temp[2].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_waiting); + regs_temp[3].flag = &(DSL_DEV_PRIVATE(pDev)->modem_ready_cnt); + regs_temp[4].flag = &(DSL_DEV_PRIVATE(pDev)->cmv_count); + regs_temp[5].flag = &(DSL_DEV_PRIVATE(pDev)->reply_count); + regs_temp[6].flag = (int *) &(DSL_DEV_PRIVATE(pDev)->Recent_indicator); + + memcpy ((char *) regs[num], (char *) regs_temp, sizeof (regs_temp)); + // procfs + meidir = proc_mkdir (MEI_DIRNAME, NULL); + if (meidir == NULL) { + IFX_MEI_EMSG ("Failed to create /proc/%s\n", MEI_DIRNAME); + return (-ENOMEM); + } + + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + entry = create_proc_entry (regs[num][i].name, + S_IWUSR | S_IRUSR | S_IRGRP | + S_IROTH, meidir); + if (entry) { + regs[num][i].low_ino = entry->low_ino; + entry->proc_fops = &IFX_MEI_ProcOperations; + } + else { + IFX_MEI_EMSG ("Failed to create /proc/%s/%s\n", MEI_DIRNAME, regs[num][i].name); + return (-ENOMEM); + } + } + return 0; +} + +/* + * Reading function for linux proc filesystem + */ +static int +IFX_MEI_ProcRead (struct file *file, char *buf, size_t nbytes, loff_t * ppos) +{ + int i_ino = (file->f_dentry->d_inode)->i_ino; + char *p = buf; + int i; + int num; + reg_entry_t *entry = NULL; + DSL_DEV_Device_t *pDev = NULL; + DSL_DEV_WinHost_Message_t m; + + for (num = 0; num < BSP_MAX_DEVICES; num++) { + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + if (regs[num][i].low_ino == (unsigned short)i_ino) { + entry = ®s[num][i]; + pDev = &dsl_devices[num]; + break; + } + } + } + if (entry == NULL) + return -EINVAL; + else if (strcmp(entry->name, "meminfo") == 0) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; + p += sprintf (p, "No Address Size\n"); + for (i = 0; i < MAX_BAR_REGISTERS; i++) { + p += sprintf (p, "BAR[%02d] Addr:0x%08X Size:%lu\n", + i, (u32) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[i].address, + DSL_DEV_PRIVATE(pDev)-> adsl_mem_info[i].size); + //printk( "BAR[%02d] Addr:0x%08X Size:%d\n",i,adsl_mem_info[i].address,adsl_mem_info[i].size); + } + *ppos += (p - buf); + } else if (strcmp(entry->name, "fw_version") == 0) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; + if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1) + return -EAGAIN; + //major:bits 0-7 + //minor:bits 8-15 + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 0, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) + return -EIO; + p += sprintf(p, "FW Version: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF); + //sub_version:bits 4-7 + //int_version:bits 0-3 + //spl_appl:bits 8-13 + //rel_state:bits 14-15 + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 54, 1, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) + return -EIO; + p += sprintf(p, "%d.%d.%d.%d\n", + (m.msg.RxMessage[4] >> 4) & 0xF, m.msg.RxMessage[4] & 0xF, + (m.msg.RxMessage[4] >> 14) & 3, (m.msg.RxMessage[4] >> 8) & 0x3F); + *ppos += (p - buf); + } else if (strcmp(entry->name, "fw_date") == 0) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; + if (DSL_DEV_PRIVATE(pDev)->modem_ready_cnt < 1) + return -EAGAIN; + + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 0, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) + return -EIO; + /* Day/Month */ + p += sprintf(p, "FW Date: %d.%d.", m.msg.RxMessage[4] & 0xFF, (m.msg.RxMessage[4] >> 8) & 0xFF); + + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 2, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) + return -EIO; + /* Year */ + p += sprintf(p, "%d ", m.msg.RxMessage[4]); + + makeCMV (H2D_CMV_READ, DSL_CMV_GROUP_INFO, 55, 1, 1, NULL, m.msg.TxMessage); + if (DSL_BSP_SendCMV (pDev, m.msg.TxMessage, YES_REPLY, m.msg.RxMessage) != DSL_DEV_MEI_ERR_SUCCESS) + return -EIO; + /* Hour:Minute */ + p += sprintf(p, "%d:%d\n", (m.msg.RxMessage[4] >> 8) & 0xFF, m.msg.RxMessage[4] & 0xFF); + + *ppos += (p - buf); + } else if (strcmp(entry->name, "version") == 0) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; + p += sprintf (p, "IFX MEI V%ld.%ld.%ld\n", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision); + + *ppos += (p - buf); + } else if (entry->flag != (int *) DSL_DEV_PRIVATE(pDev)->Recent_indicator) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; // indicates end of file + p += sprintf (p, "0x%08X\n\n", *(entry->flag)); + *ppos += (p - buf); + if ((p - buf) > nbytes) /* Assume output can be read at one time */ + return -EINVAL; + } else { + if ((int) (*ppos) / ((int) 7) == 16) + return 0; // indicate end of the message + p += sprintf (p, "0x%04X\n\n", *(((u16 *) (entry->flag)) + (int) (*ppos) / ((int) 7))); + *ppos += (p - buf); + } + return p - buf; +} + +/* + * Writing function for linux proc filesystem + */ +static ssize_t +IFX_MEI_ProcWrite (struct file *file, const char *buffer, size_t count, loff_t * ppos) +{ + int i_ino = (file->f_dentry->d_inode)->i_ino; + reg_entry_t *current_reg = NULL; + int i = 0; + int num = 0; + unsigned long newRegValue = 0; + char *endp = NULL; + DSL_DEV_Device_t *pDev = NULL; + + for (num = 0; num < BSP_MAX_DEVICES; num++) { + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + if (regs[num][i].low_ino == i_ino) { + current_reg = ®s[num][i]; + pDev = &dsl_devices[num]; + break; + } + } + } + if ((current_reg == NULL) + || (current_reg->flag == + (int *) DSL_DEV_PRIVATE(pDev)-> + Recent_indicator)) + return -EINVAL; + + newRegValue = simple_strtoul (buffer, &endp, 0); + *(current_reg->flag) = (int) newRegValue; + return (count + endp - buffer); +} +#endif //CONFIG_PROC_FS + +static int adsl_dummy_ledcallback(void) +{ + return 0; +} + +int ifx_mei_atm_led_blink(void) +{ + return g_adsl_ledcallback(); +} +EXPORT_SYMBOL(ifx_mei_atm_led_blink); + +int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr) +{ + int i; + + if ( is_showtime ) { + *is_showtime = g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ? 0 : 1; + } + + if ( port_cell ) { + for ( i = 0; i < port_cell->port_num && i < 2; i++ ) + port_cell->tx_link_rate[i] = g_tx_link_rate[i]; + } + + if ( xdata_addr ) { + if ( g_tx_link_rate[0] == 0 && g_tx_link_rate[1] == 0 ) + *xdata_addr = NULL; + else + *xdata_addr = g_xdata_addr; + } + + return 0; +} +EXPORT_SYMBOL(ifx_mei_atm_showtime_check); + +/* + * Writing function for linux proc filesystem + */ +int __init +IFX_MEI_ModuleInit (void) +{ + int i = 0; + static struct class *dsl_class; + + pr_info("IFX MEI Version %ld.%02ld.%02ld", bsp_mei_version.major, bsp_mei_version.minor, bsp_mei_version.revision); + + for (i = 0; i < BSP_MAX_DEVICES; i++) { + if (IFX_MEI_InitDevice (i) != 0) { + IFX_MEI_EMSG("Init device fail!\n"); + return -EIO; + } + IFX_MEI_InitDevNode (i); +#ifdef CONFIG_PROC_FS + IFX_MEI_InitProcFS (i); +#endif + } + for (i = 0; i <= DSL_BSP_CB_LAST ; i++) + dsl_bsp_event_callback[i].function = NULL; + +#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK + IFX_MEI_DMSG("Start loopback test...\n"); + DFE_Loopback_Test (); +#endif + dsl_class = class_create(THIS_MODULE, "ifx_mei"); + device_create(dsl_class, NULL, MKDEV(MEI_MAJOR, 0), NULL, "ifx_mei"); + return 0; +} + +void __exit +IFX_MEI_ModuleExit (void) +{ + int i = 0; + int num; + + for (num = 0; num < BSP_MAX_DEVICES; num++) { + IFX_MEI_CleanUpDevNode (num); +#ifdef CONFIG_PROC_FS + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + remove_proc_entry (regs[num][i].name, meidir); + } +#endif + } + + remove_proc_entry (MEI_DIRNAME, NULL); + for (i = 0; i < BSP_MAX_DEVICES; i++) { + for (i = 0; i < BSP_MAX_DEVICES; i++) { + IFX_MEI_ExitDevice (i); + } + } +} + +/* export function for DSL Driver */ + +/* The functions of MEI_DriverHandleGet and MEI_DriverHandleDelete are +something like open/close in kernel space , where the open could be used +to register a callback for autonomous messages and returns a mei driver context pointer (comparable to the file descriptor in user space) + The context will be required for the multi line chips future! */ + +EXPORT_SYMBOL (DSL_BSP_DriverHandleGet); +EXPORT_SYMBOL (DSL_BSP_DriverHandleDelete); + +EXPORT_SYMBOL (DSL_BSP_ATMLedCBRegister); +EXPORT_SYMBOL (DSL_BSP_ATMLedCBUnregister); +EXPORT_SYMBOL (DSL_BSP_KernelIoctls); +EXPORT_SYMBOL (DSL_BSP_AdslLedInit); +//EXPORT_SYMBOL (DSL_BSP_AdslLedSet); +EXPORT_SYMBOL (DSL_BSP_FWDownload); +EXPORT_SYMBOL (DSL_BSP_Showtime); + +EXPORT_SYMBOL (DSL_BSP_MemoryDebugAccess); +EXPORT_SYMBOL (DSL_BSP_SendCMV); + +// provide a register/unregister function for DSL driver to register a event callback function +EXPORT_SYMBOL (DSL_BSP_EventCBRegister); +EXPORT_SYMBOL (DSL_BSP_EventCBUnregister); + +module_init (IFX_MEI_ModuleInit); +module_exit (IFX_MEI_ModuleExit); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/package/system/ltq-tapi/Config.in b/package/system/ltq-tapi/Config.in new file mode 100644 index 0000000000..84dbef2397 --- /dev/null +++ b/package/system/ltq-tapi/Config.in @@ -0,0 +1,88 @@ +config VOICE_CPE_TAPI_FAX + bool "fax relay and modem support" + depends on PACKAGE_kmod-ltq-tapi + default n + help + Option to enable fax/modem support in TAPI. + Note: Newer platforms as AR9 and VR9 support a T.38 fax relay stack + in FW while older platforms like Danube or VINETIC-CPE require a + separate SW stack executed as an application. + +config VOICE_CPE_TAPI_CID + bool "CID support" + depends on PACKAGE_kmod-ltq-tapi + default y + help + Option to enable Caller ID support. + +config VOICE_CPE_TAPI_LT_GR909 + bool "Linetesting GR-909 support" + depends on PACKAGE_kmod-ltq-tapi + default y + help + Option to enable linetesting GR-909. + +config VOICE_CPE_TAPI_DECT + bool "DECT encoding for COSIC modem" + depends on PACKAGE_kmod-ltq-tapi + default n + help + Option to enable DECT encoding for COSIC modem. + +config VOICE_CPE_TAPI_KPI + bool "KPI (Kernel Packet Interface)" + depends on PACKAGE_kmod-ltq-tapi + default y + help + Option to enable the generic kernel level packet interface + which allows accelerated packet transfer for various purposes. + The most important example is the QOS option, which allows + to redirect RTP packets directly into the IP stack. + Other options relying on KPI are DECT and HDLC. + +config VOICE_CPE_TAPI_QOS + bool "QOS for accelerated RTP packet handling" + depends on PACKAGE_kmod-ltq-tapi + default y + help + Option to enable an accelerated RTP packet transfer inside + the LINUX kernel space. This option requires the KPI2UDP + packet, which actually provides the OS specific hooks in + the IP stack. + +config VOICE_CPE_TAPI_STATISTICS + bool "TAPI statistics via /proc fs" + depends on PACKAGE_kmod-ltq-tapi + default y + help + Option to enable /proc fs statistics for packet counts etc. + +config VOICE_CPE_TAPI_METERING + bool "Metering (TTX) support" + depends on PACKAGE_kmod-ltq-tapi + default n + help + Option to enable metering (TTX) support. + +config VOICE_CPE_TAPI_HDLC + bool "PCM HDLC support, evaluation" + depends on PACKAGE_kmod-ltq-tapi + default n + help + Option to enable PCM HDLC framing inside the firmware, e.g. for + ISDN D-Channel access. + +config VOICE_CPE_TAPI_TRACES + bool "enable driver traces" + depends on PACKAGE_kmod-ltq-tapi + default y + help + enable driver traces with different trace levels to be + configured dynamically from the application or during insmod + +config VOICE_CPE_TAPI_LINUX_HOTPLUG + bool "enable driver Linux hotplug events" + depends on PACKAGE_kmod-ltq-tapi + default y + help + enable driver Linux hotplug events generation diff --git a/package/system/ltq-tapi/Makefile b/package/system/ltq-tapi/Makefile new file mode 100644 index 0000000000..2582235dc9 --- /dev/null +++ b/package/system/ltq-tapi/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=drv_tapi +PKG_VERSION:=3.13.0 +PKG_RELEASE:=3 + +PKG_SOURCE:=drv_tapi-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=edb43b494832c540cc035493d18db58f +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +include $(INCLUDE_DIR)/ltqtapi.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-tapi + SUBMENU:=Voice over IP + TITLE:=Lantiq TAPI subsystem + URL:=http://www.lantiq.com/ + DEPENDS:=$(LTQ_TAPI_TARGET) +kmod-ltq-ifxos + FILES:=$(PKG_BUILD_DIR)/src/drv_tapi.ko + AUTOLOAD:=$(call AutoLoad,20,drv_tapi) +endef + +define KernelPackage/ltq-tapi/description + Voice Subsystem Telephony API High Level Driver +endef + +define KernelPackage/ltq-tapi/config + source "$(SOURCE)/Config.in" +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_IFX_DRV_TAPI_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_STATISTICS,statistics) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_METERING,metering) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LINUX_HOTPLUG,hotplug) + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include/drv_tapi + $(CP) --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_tapi + (cd $(1)/usr/include/drv_tapi && ln -s . include && ln -s ../ifxos/ifx_types.h .) +endef + +$(eval $(call KernelPackage,ltq-tapi)) diff --git a/package/system/ltq-tapi/patches/000-portability.patch b/package/system/ltq-tapi/patches/000-portability.patch new file mode 100644 index 0000000000..78fcbad668 --- /dev/null +++ b/package/system/ltq-tapi/patches/000-portability.patch @@ -0,0 +1,82 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -154,7 +154,7 @@ if KERNEL_2_6 + drv_tapi_OBJS = "$(subst .c,.o, $(drv_tapi_SOURCES))" + + drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_tapi_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -162,10 +162,10 @@ drv_tapi.ko: $(drv_tapi_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_tapi: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_tapi_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_tapi_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: +--- a/configure.in ++++ b/configure.in +@@ -128,7 +128,7 @@ dnl Set kernel build path + AC_ARG_ENABLE(kernelbuild, + AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path), + [ +- if test -r $enableval/include/linux/autoconf.h; then ++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then + AC_SUBST([KERNEL_BUILD_PATH],[$enableval]) + else + AC_MSG_ERROR([The kernel build directory is not valid or not configured!]) +--- a/src/drv_tapi_linux.h ++++ b/src/drv_tapi_linux.h +@@ -24,6 +24,7 @@ + #include <linux/version.h> + #include <linux/interrupt.h> /* in_interrupt() */ + #include <linux/delay.h> /* mdelay - udelay */ ++#include <linux/workqueue.h> /* work_struct */ + #include <asm/poll.h> /* POLLIN, POLLOUT */ + + #include "ifx_types.h" /* ifx type definitions */ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -47,6 +47,7 @@ + #include <linux/errno.h> + #include <asm/uaccess.h> /* copy_from_user(), ... */ + #include <asm/byteorder.h> ++#include <linux/smp_lock.h> /* lock_kernel() */ + #include <asm/io.h> + + #ifdef LINUX_2_6 +@@ -55,7 +56,11 @@ + #include <linux/sched.h> + #undef CONFIG_DEVFS_FS + #ifndef UTS_RELEASE +- #include "linux/utsrelease.h" ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++# include <linux/utsrelease.h> ++#else ++# include <generated/utsrelease.h> ++#endif + #endif /* UTC_RELEASE */ + #else + #include <linux/tqueue.h> +@@ -3718,7 +3723,11 @@ IFX_void_t TAPI_OS_ThreadKill(IFXOS_Thre + flag and released after the down() call. */ + lock_kernel(); + mb(); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + kill_proc(pThrCntrl->tid, SIGKILL, 1); ++#else ++ kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1); ++#endif + /* release the big kernel lock */ + unlock_kernel(); + wait_for_completion (&pThrCntrl->thrCompletion); diff --git a/package/system/ltq-tapi/patches/100-ifxmips.patch b/package/system/ltq-tapi/patches/100-ifxmips.patch new file mode 100644 index 0000000000..a9c0d8116b --- /dev/null +++ b/package/system/ltq-tapi/patches/100-ifxmips.patch @@ -0,0 +1,96 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -552,7 +552,7 @@ static ssize_t ifx_tapi_write (struct fi + IFX_uint8_t *pData; + IFX_size_t buf_size; + #endif /* TAPI_PACKET */ +- IFX_ssize_t size = 0; ++ ssize_t size = 0; + + #ifdef TAPI_PACKET + if (pTapiDev->bInitialized == IFX_FALSE) +--- a/src/drv_tapi_osmap.h ++++ b/src/drv_tapi_osmap.h +@@ -17,39 +17,6 @@ + */ + + #include "ifx_types.h" /* ifx type definitions */ +- +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_LONG_T +- #warning please update your ifx_types.h, using local definition of IFX_long_t +- /* long type - valid for 32bit systems only */ +- typedef long IFX_long_t; +- #define HAVE_IFX_LONG_T +-#endif /* HAVE_IFX_LONG_T */ +- +-#ifndef HAVE_IFX_INTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_intptr_t +- typedef IFX_long_t IFX_intptr_t; +- #define HAVE_IFX_INTPTR_T +-#endif /* HAVE_IFX_INTPTR_T */ +- +-#ifndef HAVE_IFX_SIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_size_t +- typedef IFX_ulong_t IFX_size_t; +- #define HAVE_IFX_SIZE_T +-#endif /* HAVE_IFX_SIZE_T */ +- +-#ifndef HAVE_IFX_SSIZE_T +- #warning please update your ifx_types.h, using local definition of IFX_ssize_t +- typedef IFX_long_t IFX_ssize_t; +- #define HAVE_IFX_SSIZE_T +-#endif /* HAVE_IFX_SSIZE_T */ +- + #include "ifxos_interrupt.h" + #include "ifxos_memory_alloc.h" + #include "ifxos_copy_user_space.h" +--- a/include/drv_tapi_ll_interface.h ++++ b/include/drv_tapi_ll_interface.h +@@ -40,13 +40,6 @@ + #include "ifxos_select.h" + #endif /* TAPI_PACKET */ + +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- + /* ============================= */ + /* Local Macros Definitions */ + /* ============================= */ +--- a/src/lib/lib_bufferpool/lib_bufferpool.c ++++ b/src/lib/lib_bufferpool/lib_bufferpool.c +@@ -85,24 +85,6 @@ + #include <stdlib.h> + #endif /*VXWORKS*/ + +- +-/* ============================= */ +-/* Extra type definitions */ +-/* ============================= */ +-#ifndef HAVE_IFX_ULONG_T +- #warning please update your ifx_types.h, using local definition of IFX_ulong_t +- /* unsigned long type - valid for 32bit systems only */ +- typedef unsigned long IFX_ulong_t; +- #define HAVE_IFX_ULONG_T +-#endif /* HAVE_IFX_ULONG_T */ +- +-#ifndef HAVE_IFX_UINTPTR_T +- #warning please update your ifx_types.h, using local definition of IFX_uintptr_t +- typedef IFX_ulong_t IFX_uintptr_t; +- #define HAVE_IFX_UINTPTR_T +-#endif /* HAVE_IFX_UINTPTR_T */ +- +- + /* ============================= */ + /* Local Macros & Definitions */ + /* ============================= */ diff --git a/package/system/ltq-tapi/patches/200-linux-37.patch b/package/system/ltq-tapi/patches/200-linux-37.patch new file mode 100644 index 0000000000..9d7428df03 --- /dev/null +++ b/package/system/ltq-tapi/patches/200-linux-37.patch @@ -0,0 +1,108 @@ +--- a/src/drv_tapi_linux.c ++++ b/src/drv_tapi_linux.c +@@ -47,7 +47,9 @@ + #include <linux/errno.h> + #include <asm/uaccess.h> /* copy_from_user(), ... */ + #include <asm/byteorder.h> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include <linux/smp_lock.h> /* lock_kernel() */ ++#endif + #include <asm/io.h> + + #ifdef LINUX_2_6 +@@ -65,7 +67,9 @@ + #else + #include <linux/tqueue.h> + #include <linux/sched.h> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include <linux/smp_lock.h> /* lock_kernel() */ ++#endif + #endif /* LINUX_2_6 */ + + #include "drv_tapi.h" +@@ -133,8 +137,13 @@ + size_t count, loff_t * ppos); + static ssize_t ifx_tapi_read(struct file * filp, char *buf, + size_t length, loff_t * ppos); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + static int ifx_tapi_ioctl(struct inode *inode, struct file *filp, + unsigned int nCmd, unsigned long nArgument); ++#else ++static long ifx_tapi_ioctl(struct file *filp, ++ unsigned int nCmd, unsigned long nArgument); ++#endif + static unsigned int ifx_tapi_poll (struct file *filp, poll_table *table); + + #ifdef CONFIG_PROC_FS +@@ -218,7 +227,11 @@ + IFX_char_t *pRegDrvName = IFX_NULL; + IFX_int32_t ret = 0; + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + if (tapi_fops.ioctl == IFX_NULL) ++#else ++ if (tapi_fops.unlocked_ioctl == IFX_NULL) ++#endif + { + #ifdef MODULE + tapi_fops.owner = THIS_MODULE; +@@ -226,7 +239,11 @@ + tapi_fops.read = ifx_tapi_read; + tapi_fops.write = ifx_tapi_write; + tapi_fops.poll = ifx_tapi_poll; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + tapi_fops.ioctl = ifx_tapi_ioctl; ++#else ++ tapi_fops.unlocked_ioctl = ifx_tapi_ioctl; ++#endif + tapi_fops.open = ifx_tapi_open; + tapi_fops.release = ifx_tapi_release; + } +@@ -881,8 +898,13 @@ + - 0 and positive values - success + - negative value - ioctl failed + */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + static int ifx_tapi_ioctl(struct inode *inode, struct file *filp, + unsigned int nCmd, unsigned long nArg) ++#else ++static long ifx_tapi_ioctl(struct file *filp, ++ unsigned int nCmd, unsigned long nArg) ++#endif + { + TAPI_FD_PRIV_DATA_t *pTapiPriv; + IFX_TAPI_ioctlCtx_t ctx; +@@ -3721,7 +3743,9 @@ + kernel lock (lock_kernel()). The lock must be + grabbed before changing the terminate + flag and released after the down() call. */ +- lock_kernel(); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) ++ lock_kernel(); ++#endif + mb(); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + kill_proc(pThrCntrl->tid, SIGKILL, 1); +@@ -3729,8 +3753,10 @@ + kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1); + #endif + /* release the big kernel lock */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) + unlock_kernel(); +- wait_for_completion (&pThrCntrl->thrCompletion); ++#endif ++ wait_for_completion (&pThrCntrl->thrCompletion); + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + /* Now we are sure the thread is in zombie state. +--- a/src/lib/lib_fifo/lib_fifo.c ++++ b/src/lib/lib_fifo/lib_fifo.c +@@ -41,7 +41,7 @@ + #ifdef LINUX + /* if linux/slab.h is not available, use the precessor linux/malloc.h */ + #include <linux/slab.h> +-#elif VXWORKS ++#elif defined(VXWORKS) + #include <sys_drv_debug.h> + #endif /* LINUX */ + diff --git a/package/system/ltq-vmmc/Config.in b/package/system/ltq-vmmc/Config.in new file mode 100644 index 0000000000..3a5e0145cc --- /dev/null +++ b/package/system/ltq-vmmc/Config.in @@ -0,0 +1,95 @@ +choice + prompt "device selection" + depends on PACKAGE_kmod-ltq-vmmc + default VOICE_CPE_VMMC_WITH_DEVICE_DANUBE + help + Select the target device. + + config VOICE_CPE_VMMC_WITH_DEVICE_DANUBE + bool "Danube, Twinpass, Vinax" + depends on TARGET_lantiq_danube + + config VOICE_CPE_VMMC_WITH_DEVICE_AR9 + bool "AR9 family" + depends on TARGET_lantiq_ar9 + + config VOICE_CPE_VMMC_WITH_DEVICE_VR9 + bool "VR9 family" + depends on TARGET_lantiq_vr9 + + config VOICE_VMMC_WITH_DEVICE_FALCON + bool "FALC-ON" + depends on (TARGET_lantiq_falcon||TARGET_lantiq_falcon_stable) + +endchoice + +choice + depends on PACKAGE_kmod-ltq-vmmc + prompt "FXS coefficients" + default LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI + help + Select country specific FXS coefficient file. + + config LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI + bool "ETSI_T3R10: Vl:40V, Ic:25mA, Vid:25V, Vri:45Vrms, f:25Hz" + help + These coefficents contains a parameter set with line impedance Zr according to ETSI. + + T: gain in transmit direction (attenuation 3dBr) [dBr] + R: gain in receive direction (attenuation 10dBr) [dBr] + Vl: on-hook voltage limit [V] + Ic: off-hook loop current [mA] + Vid: low-power-standby voltage [V] + Vri: ring voltage [v] + f: ring frequency [V] + + config LTQ_VOICE_CPE_VMMC_COEF_FALCON_US600R + bool "USA_600R_T3R10: Vl:40V, Ic:25mA, Vid:25V, Vri:45V, f:20Hz" + help + These coefficents contains a parameter set with line impedance e.g. for USA. + + T: gain in transmit direction (attenuation 3dBr) [dBr] + R: gain in receive direction (attenuation 10dBr) [dBr] + Vl: on-hook voltage limit [V] + Ic: off-hook loop current [mA] + Vid: low-power-standby voltage [V] + Vri: ring voltage [v] + f: ring frequency [V] + + config LTQ_VOICE_CPE_VMMC_COEF_FALCON_USE_CUSTOM_FILE + bool "Select own FXS coefficient file" +endchoice + +config VOICE_CPE_VMMC_PMC + depends on (VOICE_CPE_VMMC_WITH_DEVICE_AR9 || VOICE_CPE_VMMC_WITH_DEVICE_VR9) + bool "Power Management Control support" + default n + help + Option to enable Power Management Control on AR9, VR9. Not supported for Danube. + +config VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP + bool "Disable DECT nibble swap" + depends on PACKAGE_kmod-ltq-vmmc + default n + help + Option to disable DECT nibble swap for COSIC modem (for backward compatibility only). + +config VOICE_CPE_VMMC_EVENT_LOGGER + depends on BROKEN + bool "Event logger support" + depends on PACKAGE_kmod-ltq-vmmc + default n + help + Option to enable details traces between drv_vmmc and the voice FW + - for debugging only + - requires package ifx-evtlog + +config VOICE_CPE_VMMC_MPS_HISTORY_SIZE + int "MPS history buffer in words (0<=size<=512)" + depends on PACKAGE_kmod-ltq-vmmc + default "128" + help + MPS history buffer (default=128 words, maximum=512 words, 0=disable) + To opimize the memory footprint in RAM, you might want to set the + buffer size to 0. + diff --git a/package/system/ltq-vmmc/Makefile b/package/system/ltq-vmmc/Makefile new file mode 100644 index 0000000000..98355b1ecd --- /dev/null +++ b/package/system/ltq-vmmc/Makefile @@ -0,0 +1,166 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=drv_vmmc +PKG_VERSION:=1.9.0 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_MD5SUM:=d8eee8cba0edb28974cc1f8532e3bd18 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +include $(INCLUDE_DIR)/ltqtapi.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-vmmc + SUBMENU:=Voice over IP + TITLE:=TAPI LL driver for Voice Macro + URL:=http://www.lantiq.com/ + DEPENDS:=$(LTQ_TAPI_TARGET) +kmod-ltq-tapi + FILES:=$(PKG_BUILD_DIR)/src/drv_vmmc.ko + AUTOLOAD:=$(call AutoLoad,25,drv_vmmc) +endef + +define KernelPackage/ltq-vmmc/description + Voice Subsystem Low Level Driver for Danube, AR9, VR9 device families +endef + +define KernelPackage/ltq-vmmc/config + source "$(SOURCE)/Config.in" +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_EVENT_LOGGER,el-debug) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_PMC,pmc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_VMMC_DISABLE_DECT_NIBBLE_SWAP,dect-nibble-swap) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_FAX,fax t38) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_CID,cid) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_DECT,dect) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_KPI,kpi) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_LT_GR909,lt calibration) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_HDLC,hdlc) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_TRACES,trace) + +ifneq ($(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE),128) + CONFIGURE_ARGS += --enable-history-buf=$(CONFIG_VOICE_CPE_VMMC_MPS_HISTORY_SIZE) +endif + +#defaults +FW_URL:=http://localhost/ +FW_TARGET:=ifx_firmware.bin +FW_FILE:=fw_voip_ifx.tar.gz +COEF_TARGET:=ifx_bbd_fxs.bin +COEF_FILE:=coef_voip_ifx.tar.gz + +FW_DIR:=lib/firmware + +FW_TARGET_GENERIC:=$(FW_TARGET) +COEF_TARGET_GENERIC:=$(COEF_TARGET) + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE)$(CONFIG_LTQ_VOICE_CPE_VMMC_WITH_DEVICE_DANUBE),y) + CONFIGURE_ARGS += --with-device=DANUBE + FW_SOURCE:=voip_R12.1.0.1.0-enc.bin + FW_TARGET:=danube_firmware.bin + FW_FILE=fw_voip_danube-12.1.0.1.0.tar.gz + FW_MD5SUM:=51868b88dee9dbc65d3dbba355ded91c + FW_DOWNLOAD:=1 + COEF_SRC:=danube_bbd_fxs.bin + COEF_TARGET:=danube_bbd_fxs.bin + COEF_FILE:=coef_voip_danube-0.9.0.tar.gz + COEF_MD5SUM:=c8ac6592b304b03829a8123560e15710 + COEF_DOWNLOAD:=1 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_AR9),y) + CONFIGURE_ARGS += --with-device=AR9 + # TODO: add fw/coef +endif + +COEF_SRC:=$(COEF_TARGET) + +ifeq ($(CONFIG_VOICE_VMMC_WITH_DEVICE_FALCON),y) + CONFIGURE_ARGS += --with-device=FALCON + FW_SOURCE:=voip_R1.1.0.6.0-enc.bin + FW_MD5SUM:=cd4366a52a8010b76793e3810a4f14b3 + FW_TARGET:=falcon_voip_fw.bin + FW_FILE=fw_voip_falcon-1.1.0.6.0.tar.gz + FW_DOWNLOAD:=1 + COEF_TARGET:=falcon_bbd.bin +# FXS part +ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_ETSI),y) + COEF_SRC:=ETSI_3_10.BIN +endif +ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_US600R),y) + COEF_SRC:=R600_3_10.BIN +endif +ifeq ($(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_USE_CUSTOM_FILE),y) + COEF_SRC:=$(CONFIG_LTQ_VOICE_CPE_VMMC_COEF_FALCON_CUSTOM_FILE) +endif + COEF_FILE:=coef_voip_falcon.tar.gz + COEF_MD5SUM:=56c5a838f2bb9bd87d0e8dce271f810b + COEF_DOWNLOAD:=1 +endif + +ifeq ($(CONFIG_VOICE_CPE_VMMC_WITH_DEVICE_VR9),y) + CONFIGURE_ARGS += --with-device=VR9 + # TODO: add fw/coef +endif + +define Download/firmware + FILE:=$(FW_FILE) + URL:=$(FW_URL) + MD5SUM:=$(FW_MD5SUM) +endef +$(eval $(if $(FW_DOWNLOAD),$(call Download,firmware))) + +define Download/coef + FILE:=$(COEF_FILE) + URL:=$(FW_URL) + MD5SUM:=$(COEF_MD5SUM) +endef +$(eval $(if $(COEF_DOWNLOAD),$(call Download,coef))) + +define Build/Configure + rm -rf \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware + mkdir -p \ + $(PKG_BUILD_DIR)/coef \ + $(PKG_BUILD_DIR)/firmware + $(TAR) -C $(PKG_BUILD_DIR)/firmware -xvzf $(DL_DIR)/$(FW_FILE) + $(TAR) -C $(PKG_BUILD_DIR)/coef -xvzf $(DL_DIR)/$(COEF_FILE) + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + mkdir -p $(1)/usr/include/drv_vmmc + $(CP) -v --dereference $(PKG_BUILD_DIR)/include/* $(1)/usr/include/drv_vmmc + (cd $(1)/usr/include/drv_vmmc && ln -snf . include) +endef + +define KernelPackage/ltq-vmmc/install + $(INSTALL_DIR) $(1)/etc/init.d $(1)/$(FW_DIR) + $(INSTALL_BIN) ./files/vmmc.init $(1)/etc/init.d/vmmc + $(CP) $(PKG_BUILD_DIR)/firmware/$(FW_SOURCE) $(1)/$(FW_DIR)/$(FW_TARGET) + ln -s /$(FW_DIR)/$(FW_TARGET) $(1)/$(FW_DIR)/$(FW_TARGET_GENERIC) + $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_SRC) $(1)/$(FW_DIR)/$(COEF_TARGET) + ln -s /$(FW_DIR)/$(COEF_TARGET) $(1)/$(FW_DIR)/$(COEF_TARGET_GENERIC) +endef + +$(eval $(call KernelPackage,ltq-vmmc)) diff --git a/package/system/ltq-vmmc/files/vmmc.init b/package/system/ltq-vmmc/files/vmmc.init new file mode 100644 index 0000000000..100a97dc45 --- /dev/null +++ b/package/system/ltq-vmmc/files/vmmc.init @@ -0,0 +1,19 @@ +#!/bin/sh /etc/rc.common +# +# Activate Voice CPE TAPI subsystem LL driver for VMMC + +START=31 + +start() { + [ ! -c /dev/vmmc10 ] && { + mknod /dev/vmmc10 c 122 10 + mknod /dev/vmmc11 c 122 11 + mknod /dev/vmmc12 c 122 12 + mknod /dev/vmmc13 c 122 13 + mknod /dev/vmmc14 c 122 14 + mknod /dev/vmmc15 c 122 15 + mknod /dev/vmmc16 c 122 16 + mknod /dev/vmmc17 c 122 17 + mknod /dev/vmmc18 c 122 18 + } +} diff --git a/package/system/ltq-vmmc/patches/000-portability.patch b/package/system/ltq-vmmc/patches/000-portability.patch new file mode 100644 index 0000000000..48602476f4 --- /dev/null +++ b/package/system/ltq-vmmc/patches/000-portability.patch @@ -0,0 +1,287 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -228,7 +228,7 @@ drv_vmmc_CFLAGS += -fno-common + drv_vmmc_OBJS = "$(subst .c,.o, $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES))" + + drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA_DIST) +- @echo -e "Making Linux 2.6.x kernel object" ++ @echo "Making Linux 2.6.x kernel object" + @for f in $(drv_vmmc_SOURCES) $(nodist_drv_vmmc_SOURCES) ; do \ + if test ! -e $(PWD)/$$f; then \ + echo " LN $$f" ; \ +@@ -236,10 +236,10 @@ drv_vmmc.ko: $(drv_vmmc_SOURCES) $(EXTRA + ln -s @abs_srcdir@/$$f $(PWD)/$$f; \ + fi; \ + done; +- @echo -e "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild +- @echo -e "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild +- @echo -e "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild +- @echo -e "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild ++ @echo "# drv_vmmc: Generated to build Linux 2.6.x kernel object" > $(PWD)/Kbuild ++ @echo "obj-m := $(subst .ko,.o,$@)" >> $(PWD)/Kbuild ++ @echo "$(subst .ko,,$@)-y := $(drv_vmmc_OBJS)" >> $(PWD)/Kbuild ++ @echo "EXTRA_CFLAGS := -DHAVE_CONFIG_H $(CFLAGS) $(drv_vmmc_CFLAGS) $(INCLUDES)" >> $(PWD)/Kbuild + $(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules + + clean-generic: +--- a/src/drv_vmmc_linux.c ++++ b/src/drv_vmmc_linux.c +@@ -27,11 +27,18 @@ + #include <linux/proc_fs.h> + #include <linux/wait.h> + #include <linux/vmalloc.h> ++#include <linux/sched.h> + + #ifdef LINUX_2_6 + #include <linux/version.h> + #ifndef UTS_RELEASE ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++#include <linux/autoconf.h> + #include <linux/utsrelease.h> ++#else ++#include <generated/autoconf.h> ++#include <generated/utsrelease.h> ++#endif + #endif /* UTC_RELEASE */ + #undef CONFIG_DEVFS_FS + #endif /* LINUX_2_6 */ +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -19,11 +19,22 @@ + #include "drv_config.h" + + #include "drv_mps_version.h" ++#include <linux/version.h> + + #ifdef CONFIG_DEBUG_MINI_BOOT + #define IKOS_MINI_BOOT + #endif /* */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include <linux/autoconf.h> ++#ifndef UTS_RELEASE ++#include <linux/utsrelease.h> ++#endif ++#else ++#include <generated/autoconf.h> ++#ifndef UTS_RELEASE ++#include <generated/utsrelease.h> ++#endif ++#endif + #include <linux/module.h> + #include <linux/init.h> + #include <linux/poll.h> +@@ -34,7 +45,13 @@ + #include <linux/delay.h> + #include <linux/interrupt.h> + #ifdef LINUX_2_6 ++#ifndef UTS_RELEASE ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) + #include <linux/utsrelease.h> ++#else ++#include <generated/utsrelease.h> ++#endif ++#endif /* UTC_RELEASE */ + #else /* */ + #include <linux/uts.h> + #include <linux/moduleparam.h> +@@ -94,8 +111,13 @@ IFX_int32_t ifx_mps_get_status_proc (IFX + #ifndef __KERNEL__ + IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p); + IFX_int32_t ifx_mps_close (struct inode *inode, struct file *file_p); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + IFX_int32_t ifx_mps_ioctl (struct inode *inode, struct file *file_p, + IFX_uint32_t nCmd, IFX_ulong_t arg); ++#else ++long ifx_mps_ioctl (struct file *file_p, ++ IFX_uint32_t nCmd, IFX_ulong_t arg); ++#endif + IFX_int32_t ifx_mps_read_mailbox (mps_devices type, mps_message * rw); + IFX_int32_t ifx_mps_write_mailbox (mps_devices type, mps_message * rw); + IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir, +@@ -155,7 +177,11 @@ IFX_char_t voice_channel_int_name[NUM_VO + static struct file_operations ifx_mps_fops = { + owner:THIS_MODULE, + poll:ifx_mps_poll, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ioctl:ifx_mps_ioctl, ++#else ++ unlocked_ioctl:ifx_mps_ioctl, ++#endif + open:ifx_mps_open, + release:ifx_mps_close + }; +@@ -598,8 +624,13 @@ static IFX_uint32_t ifx_mps_poll (struct + * \return -ENOIOCTLCMD Invalid command + * \ingroup API + */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + IFX_int32_t ifx_mps_ioctl (struct inode * inode, struct file * file_p, + IFX_uint32_t nCmd, IFX_ulong_t arg) ++#else ++long ifx_mps_ioctl (struct file *file_p, ++ IFX_uint32_t nCmd, IFX_ulong_t arg) ++#endif + { + IFX_int32_t retvalue = -EINVAL; + mps_message rw_struct; +@@ -613,17 +644,30 @@ IFX_int32_t ifx_mps_ioctl (struct inode + 'mps_devices' enum type, which in fact is [0..8]; So, if inode value is + [0..NUM_VOICE_CHANNEL+1], then we make sure that we are calling from + kernel space. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + if (((IFX_int32_t) inode >= 0) && + ((IFX_int32_t) inode < NUM_VOICE_CHANNEL + 1)) ++#else ++ if (((IFX_int32_t) file_p >= 0) && ++ ((IFX_int32_t) file_p < NUM_VOICE_CHANNEL + 1)) ++#endif + { + from_kernel = 1; + + /* Get corresponding mailbox device structure */ + if ((pMBDev = ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ifx_mps_get_device ((mps_devices) ((IFX_int32_t) inode))) == 0) ++#else ++ ifx_mps_get_device ((mps_devices) ((IFX_int32_t) file_p))) == 0) ++#endif + { + return (-EINVAL); + } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) ++#else ++ file_p = NULL; ++#endif + } + else + { +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -21,7 +21,11 @@ + #undef USE_PLAIN_VOICE_FIRMWARE + #undef PRINT_ON_ERR_INTERRUPT + #undef FAIL_ON_ERR_INTERRUPT ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include <linux/autoconf.h> ++#else ++#include <generated/autoconf.h> ++#endif + #include <linux/interrupt.h> + #include <linux/delay.h> + +@@ -92,7 +96,9 @@ extern IFX_uint32_t danube_get_cpu_ver ( + extern mps_mbx_dev *ifx_mps_get_device (mps_devices type); + + #ifdef LINUX_2_6 ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) + extern IFX_void_t bsp_mask_and_ack_irq (IFX_uint32_t irq_nr); ++#endif + + #else /* */ + extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr); +--- a/src/mps/drv_mps_vmmc_danube.c ++++ b/src/mps/drv_mps_vmmc_danube.c +@@ -20,7 +20,11 @@ + + #ifdef SYSTEM_DANUBE /* defined in drv_mps_vmmc_config.h */ + ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include <linux/autoconf.h> ++#else ++#include <generated/autoconf.h> ++#endif + + /* lib_ifxos headers */ + #include "ifx_types.h" +--- a/configure.in ++++ b/configure.in +@@ -112,7 +112,7 @@ dnl Set kernel build path + AC_ARG_ENABLE(kernelbuild, + AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path), + [ +- if test -r $enableval/include/linux/autoconf.h; then ++ if test -e $enableval/include/linux/autoconf.h -o -e $enableval/include/generated/autoconf.h; then + AC_SUBST([KERNEL_BUILD_PATH],[$enableval]) + else + AC_MSG_ERROR([The kernel build directory is not valid or not configured!]) +--- a/src/drv_vmmc_bbd.c ++++ b/src/drv_vmmc_bbd.c +@@ -1072,7 +1072,11 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + IFX_uint8_t padBytes = 0; + #endif + IFX_uint16_t cram_offset, cram_crc, +- pCmd [MAX_CMD_WORD] = {0}; ++ pCmd [MAX_CMD_WORD] ++#if defined (__GNUC__) || defined (__GNUG__) ++ __attribute__ ((aligned(4))) ++#endif ++ = {0}; + + /* read offset */ + cpb2w (&cram_offset, &bbd_cram->pData[0], sizeof (IFX_uint16_t)); +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -776,8 +776,13 @@ IFX_int32_t VMMC_TAPI_LL_FW_Start(IFX_TA + dwld.fwDwld.length = IoInit.pram_size; + + /* download firmware */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ret = ifx_mps_ioctl((IFX_void_t *) command, IFX_NULL, FIO_MPS_DOWNLOAD, + (IFX_uint32_t) &dwld.fwDwld); ++#else ++ ret = ifx_mps_ioctl((IFX_void_t *) command, FIO_MPS_DOWNLOAD, ++ (IFX_uint32_t) &dwld.fwDwld); ++#endif + } + + if (VMMC_SUCCESS(ret)) +--- a/src/drv_vmmc_ioctl.c ++++ b/src/drv_vmmc_ioctl.c +@@ -426,18 +426,31 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP + /* MPS driver will do the USR2KERN so just pass on the pointer. */ + dwnld_struct.data = (IFX_void_t *)IoInit.pPRAMfw; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL, + FIO_MPS_DOWNLOAD, (IFX_uint32_t) &dwnld_struct); ++#else ++ ret = ifx_mps_ioctl((IFX_void_t *)command, ++ FIO_MPS_DOWNLOAD, (IFX_uint32_t) &dwnld_struct); ++#endif + break; + } + case FIO_DEV_RESET: + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL, FIO_MPS_RESET, 0); ++#else ++ ret = ifx_mps_ioctl((IFX_void_t *)command, FIO_MPS_RESET, 0); ++#endif + break; + } + case FIO_DEV_RESTART: + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + ret = ifx_mps_ioctl((IFX_void_t *)command, IFX_NULL, FIO_MPS_RESTART, 0); ++#else ++ ret = ifx_mps_ioctl((IFX_void_t *)command, FIO_MPS_RESTART, 0); ++#endif + break; + } + case FIO_LASTERR: +--- a/src/mps/drv_mps_vmmc.h ++++ b/src/mps/drv_mps_vmmc.h +@@ -279,8 +279,13 @@ typedef struct + #include <linux/fs.h> + IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p); + IFX_int32_t ifx_mps_close (struct inode *inode, struct file *filp); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + IFX_int32_t ifx_mps_ioctl (struct inode *inode, struct file *file_p, + IFX_uint32_t nCmd, unsigned long arg); ++#else ++long ifx_mps_ioctl (struct file *filp, ++ IFX_uint32_t nCmd, unsigned long arg); ++#endif + IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir, + IFX_void_t (*callback) (mps_devices + type)); diff --git a/package/system/ltq-vmmc/patches/100-target.patch b/package/system/ltq-vmmc/patches/100-target.patch new file mode 100644 index 0000000000..eae621eafd --- /dev/null +++ b/package/system/ltq-vmmc/patches/100-target.patch @@ -0,0 +1,738 @@ +--- a/src/drv_vmmc_access.h ++++ b/src/drv_vmmc_access.h +@@ -24,6 +24,10 @@ + #include "drv_mps_vmmc.h" + #endif + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS IFXMIPS_MPS_BASE_ADDR ++#endif ++ + /* ============================= */ + /* Global Defines */ + /* ============================= */ +--- a/src/drv_vmmc_danube.h ++++ b/src/drv_vmmc_danube.h +@@ -15,56 +15,18 @@ + */ + + #if defined SYSTEM_DANUBE +-#include <asm/ifx/ifx_gpio.h> ++#include <lantiq_soc.h> ++ + #else + #error no system selected + #endif + +-#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC ++#define VMMC_TAPI_GPIO_MODULE_ID IFX_GPIO_MODULE_TAPI_VMMC + /** + + */ + #define VMMC_PCM_IF_CFG_HOOK(mode, GPIOreserved, ret) \ + do { \ +- ret = VMMC_statusOk; \ +- /* Reserve P0.0 as TDM/FSC */ \ +- if (!GPIOreserved) \ +- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel1_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID);\ +- \ +- /* Reserve P1.9 as TDM/DO */ \ +- if (!GPIOreserved) \ +- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel1_clear(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- \ +- /* Reserve P1.10 as TDM/DI */ \ +- if (!GPIOreserved) \ +- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel0_clear(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel1_set(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID);\ +- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \ +- \ +- /* Reserve P1.11 as TDM/DCL */ \ +- if (!GPIOreserved) \ +- ret |= ifx_gpio_pin_reserve(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel0_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_altsel1_clear(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_open_drain_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- \ +- if (mode == 2) { \ +- /* TDM/FSC+DCL Master */ \ +- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_dir_out_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- } else { \ +- /* TDM/FSC+DCL Slave */ \ +- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_dir_in_set(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ +- } \ + } while(0); + + /** +@@ -72,11 +34,6 @@ + */ + #define VMMC_DRIVER_UNLOAD_HOOK(ret) \ + do { \ +- ret = VMMC_statusOk; \ +- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(0, 0), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1, 9), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1,10), VMMC_TAPI_GPIO_MODULE_ID); \ +- ret |= ifx_gpio_pin_free(IFX_GPIO_PIN_ID(1,11), VMMC_TAPI_GPIO_MODULE_ID); \ + } while (0) + + #endif /* _DRV_VMMC_AMAZON_S_H */ +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -52,6 +52,14 @@ + #include "ifx_pmu.h" + #endif /* PMU_SUPPORTED */ + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR ++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR ++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR ++#endif + + /* ============================= */ + /* Local Macros & Definitions */ +@@ -1591,7 +1599,7 @@ + #ifdef VMMC_DRIVER_UNLOAD_HOOK + if (VDevices[0].nDevState & DS_GPIO_RESERVED) + { +- IFX_int32_t ret; ++ IFX_int32_t ret = 0; + VMMC_DRIVER_UNLOAD_HOOK(ret); + if (!VMMC_SUCCESS(ret)) + { +--- a/src/drv_vmmc_init_cap.c ++++ b/src/drv_vmmc_init_cap.c +@@ -22,6 +22,11 @@ + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_device.h" + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# define IFX_MPS_CHIPID_VERSION_GET IFXMIPS_MPS_CHIPID_VERSION_GET ++# define IFX_MPS_CHIPID IFXMIPS_MPS_CHIPID ++#endif ++ + /* ============================= */ + /* Configuration defintions */ + /* ============================= */ +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -17,6 +17,7 @@ + /* Includes */ + /* ============================= */ + #include "drv_config.h" ++#include "drv_vmmc_init.h" + + #undef USE_PLAIN_VOICE_FIRMWARE + #undef PRINT_ON_ERR_INTERRUPT +@@ -39,8 +40,32 @@ + #include "ifxos_interrupt.h" + #include "ifxos_time.h" + +-#include <asm/ifx/ifx_regs.h> +-#include <asm/ifx/ifx_gptu.h> ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include <lantiq.h> ++# include <irq.h> ++# include <lantiq_timer.h> ++ ++# define ifx_gptu_timer_request lq_request_timer ++# define ifx_gptu_timer_start lq_start_timer ++# define ifx_gptu_countvalue_get lq_get_count_value ++# define ifx_gptu_timer_free lq_free_timer ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) ++# define bsp_mask_and_ack_irq ltq_mask_and_ack_irq ++#else ++extern void ltq_mask_and_ack_irq(struct irq_data *d); ++static void inline bsp_mask_and_ack_irq(int x) ++{ ++ struct irq_data d; ++ d.irq = x; ++ ltq_mask_and_ack_irq(&d); ++} ++#endif ++#else ++# include <asm/ifx/ifx_regs.h> ++# include <asm/ifx/ifx_gptu.h> ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -104,6 +129,9 @@ + extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr); + + #endif /* */ ++ ++extern void sys_hw_setup (void); ++ + extern IFXOS_event_t fw_ready_evt; + /* callback function to free all data buffers currently used by voice FW */ + IFX_void_t (*ifx_mps_bufman_freeall)(IFX_void_t) = IFX_NULL; +@@ -207,7 +235,8 @@ + */ + IFX_void_t *ifx_mps_fastbuf_malloc (IFX_size_t size, IFX_int32_t priority) + { +- IFX_uint32_t ptr, flags; ++ IFXOS_INTSTAT flags; ++ IFX_uint32_t ptr; + IFX_int32_t index = fastbuf_index; + + if (fastbuf_initialized == 0) +@@ -261,7 +290,7 @@ + */ + IFX_void_t ifx_mps_fastbuf_free (const IFX_void_t * ptr) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + IFX_int32_t index = fastbuf_index; + + IFXOS_LOCKINT (flags); +@@ -457,7 +486,7 @@ + */ + static IFX_int32_t ifx_mps_bufman_inc_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + if (mps_buffer.buf_level + value > MPS_BUFFER_MAX_LEVEL) + { +@@ -484,7 +513,7 @@ + */ + static IFX_int32_t ifx_mps_bufman_dec_level (IFX_uint32_t value) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + if (mps_buffer.buf_level < value) + { +@@ -636,7 +665,7 @@ + mem_seg_ptr[i] = + (IFX_uint32_t *) CPHYSADDR ((IFX_uint32_t) mps_buffer. + malloc (segment_size, FASTBUF_FW_OWNED)); +- if (mem_seg_ptr[i] == CPHYSADDR (IFX_NULL)) ++ if (mem_seg_ptr[i] == (IFX_uint32_t *)CPHYSADDR (IFX_NULL)) + { + TRACE (MPS, DBG_LEVEL_HIGH, + ("%s(): cannot allocate buffer\n", __FUNCTION__)); +@@ -952,7 +981,7 @@ + mps_mbx_dev * pMBDev, IFX_int32_t bcommand, + IFX_boolean_t from_kernel) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + IFXOS_LOCKINT (flags); + +@@ -1068,7 +1097,7 @@ + IFX_void_t ifx_mps_release_structures (mps_comm_dev * pDev) + { + IFX_int32_t count; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + IFXOS_LOCKINT (flags); + IFXOS_BlockFree (pFW_img_data); +@@ -1117,7 +1146,7 @@ + + /* Initialize MPS main structure */ + memset ((IFX_void_t *) pDev, 0, sizeof (mps_comm_dev)); +- pDev->base_global = (mps_mbx_reg *) IFX_MPS_SRAM; ++ pDev->base_global = (mps_mbx_reg *) IFXMIPS_MPS_SRAM; + pDev->flags = 0x00000000; + MBX_Memory = pDev->base_global; + +@@ -1125,9 +1154,11 @@ + for MBX communication. These are: mailbox base address, mailbox size, * + mailbox read index and mailbox write index. for command and voice + mailbox, * upstream and downstream direction. */ +- memset ((IFX_void_t *) MBX_Memory, /* avoid to overwrite CPU boot +- registers */ +- 0, sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg)); ++ memset ( ++ /* avoid to overwrite CPU boot registers */ ++ (IFX_void_t *) MBX_Memory, ++ 0, ++ sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg)); + MBX_Memory->MBX_UPSTR_CMD_BASE = + (IFX_uint32_t *) CPHYSADDR ((IFX_uint32_t) MBX_UPSTRM_CMD_FIFO_BASE); + MBX_Memory->MBX_UPSTR_CMD_SIZE = MBX_CMD_FIFO_SIZE; +@@ -1564,7 +1595,7 @@ + IFX_uint32_t * bytes) + { + IFX_int32_t i, ret; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + IFXOS_LOCKINT (flags); + +@@ -1774,7 +1805,7 @@ + { + mps_fifo *mbx; + IFX_uint32_t i; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + IFX_int32_t retval = -EAGAIN; + IFX_int32_t retries = 0; + IFX_uint32_t word = 0; +@@ -2169,6 +2200,7 @@ + TRACE (MPS, DBG_LEVEL_HIGH, + ("%s(): Invalid device ID %d !\n", __FUNCTION__, pMBDev->devID)); + } ++ + return retval; + } + +@@ -2192,7 +2224,7 @@ + mps_mbx_dev *mbx_dev; + MbxMsg_s msg; + IFX_uint32_t bytes_read = 0; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + IFX_int32_t ret; + + /* set pointer to data upstream mailbox, no matter if 0,1,2 or 3 because +@@ -2283,7 +2315,7 @@ + { + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2326,7 +2358,7 @@ + #endif /* CONFIG_PROC_FS */ + ifx_mps_bufman_dec_level (1); + if ((ifx_mps_bufman_get_level () <= mps_buffer.buf_threshold) && +- (atomic_read (&pMPSDev->provide_buffer->object.count) == 0)) ++ ((volatile unsigned int)pMPSDev->provide_buffer->object.count == 0)) + { + IFXOS_LockRelease (pMPSDev->provide_buffer); + } +@@ -2356,7 +2388,7 @@ + IFX_void_t ifx_mps_mbx_cmd_upstream (IFX_ulong_t dummy) + { + mps_fifo *mbx; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + /* set pointer to upstream command mailbox */ + mbx = &(pMPSDev->cmd_upstrm_fifo); +@@ -2404,7 +2436,7 @@ + mps_event_msg msg; + IFX_int32_t length = 0; + IFX_int32_t read_length = 0; +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + + /* set pointer to upstream event mailbox */ + mbx = &(pMPSDev->event_upstrm_fifo); +@@ -2619,6 +2651,7 @@ + #endif + + *IFX_MPS_AD0ENR = Ad0Reg.val; ++ + } + + /** +@@ -2647,7 +2680,7 @@ + */ + IFX_void_t ifx_mps_dd_mbx_int_enable (IFX_void_t) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2673,7 +2706,7 @@ + */ + IFX_void_t ifx_mps_dd_mbx_int_disable (IFX_void_t) + { +- IFX_uint32_t flags; ++ IFXOS_INTSTAT flags; + MPS_Ad0Reg_u Ad0Reg; + + IFXOS_LOCKINT (flags); +@@ -2738,7 +2771,6 @@ + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ +- + /* FW is up and ready to process commands */ + if (MPS_Ad0StatusReg.fld.dl_end) + { +@@ -2800,6 +2832,7 @@ + } + } + ++ + if (MPS_Ad0StatusReg.fld.du_mbx) + { + #ifdef CONFIG_PROC_FS +@@ -2944,12 +2977,12 @@ + IFX_MPS_CVC0SR[chan] = MPS_VCStatusReg.val; + /* handle only enabled interrupts */ + MPS_VCStatusReg.val &= IFX_MPS_VC0ENR[chan]; +- + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++ + pMPSDev->event.MPS_VCStatReg[chan].val = MPS_VCStatusReg.val; + #ifdef PRINT_ON_ERR_INTERRUPT + if (MPS_VCStatusReg.fld.rcv_ov) +@@ -3093,7 +3126,8 @@ + */ + IFX_return_t ifx_mps_init_gpt () + { +- IFX_uint32_t flags, timer_flags, timer, loops = 0; ++ unsigned long flags; ++ IFX_uint32_t timer_flags, timer, loops = 0; + IFX_ulong_t count; + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + timer = TIMER1A; +@@ -3166,6 +3200,7 @@ + #else /* Danube */ + timer = TIMER1B; + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ ++ + ifx_gptu_timer_free (timer); + } + +--- a/src/mps/drv_mps_vmmc_danube.c ++++ b/src/mps/drv_mps_vmmc_danube.c +@@ -16,6 +16,7 @@ + /* ============================= */ + /* Includes */ + /* ============================= */ ++#include "linux/version.h" + #include "drv_config.h" + + #ifdef SYSTEM_DANUBE /* defined in drv_mps_vmmc_config.h */ +@@ -36,9 +37,22 @@ + #include "ifxos_select.h" + #include "ifxos_interrupt.h" + +-#include <asm/ifx/ifx_regs.h> +-#include <asm/ifx/ifx_gpio.h> +-#include <asm/ifx/common_routines.h> ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include <lantiq.h> ++# include <irq.h> ++# include <lantiq_timer.h> ++# include <linux/dma-mapping.h> ++ ++ ++#define LQ_RCU_BASE_ADDR (KSEG1 + LTQ_RCU_BASE_ADDR) ++# define LQ_RCU_RST ((u32 *)(LQ_RCU_BASE_ADDR + 0x0010)) ++#define IFX_RCU_RST_REQ_CPU1 (1 << 3) ++# define IFX_RCU_RST_REQ LQ_RCU_RST ++#else ++# include <asm/ifx/ifx_regs.h> ++# include <asm/ifx_vpe.h> ++# include <asm/ifx/ifx_gpio.h> ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -75,6 +89,20 @@ + /* Local function definition */ + /* ============================= */ + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++IFX_uint32_t ifx_get_cp1_size(IFX_void_t) ++{ ++ return 1; ++} ++ ++unsigned int *ltq_get_cp1_base(void); ++ ++IFX_uint32_t *ifx_get_cp1_base(IFX_void_t) ++{ ++ return ltq_get_cp1_base(); ++} ++#endif ++ + /****************************************************************************** + * DANUBE Specific Routines + ******************************************************************************/ +@@ -134,6 +162,15 @@ + } + + /* check if FW image fits in available memory space */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++ if (mem > ifx_get_cp1_size()<<20) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n", ++ __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size()<<20)); ++ return IFX_ERROR; ++ } ++#else + if (mem > ifx_get_cp1_size()) + { + TRACE (MPS, DBG_LEVEL_HIGH, +@@ -141,6 +178,7 @@ + __FILE__, __func__, __LINE__, mem, ifx_get_cp1_size())); + return IFX_ERROR; + } ++#endif + + /* reset the driver */ + ifx_mps_reset (); +@@ -361,7 +399,7 @@ + */ + IFX_void_t ifx_mps_wdog_expiry() + { +- IFX_uint32_t flags; ++ unsigned long flags; + + IFXOS_LOCKINT (flags); + /* recalculate and compare the firmware checksum */ +--- a/src/mps/drv_mps_vmmc_device.h ++++ b/src/mps/drv_mps_vmmc_device.h +@@ -16,8 +16,58 @@ + declarations. + *******************************************************************************/ + +-#include <asm/ifx/ifx_regs.h> +-#include <asm/ifx_vpe.h> ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include <lantiq.h> ++# include <irq.h> ++# include <lantiq_soc.h> ++# include <gpio.h> ++#define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000)) ++#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000) ++#define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344)) ++#define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000)) ++#define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010)) ++#define IFXMIPS_MPS_CVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0030)) ++#define IFXMIPS_MPS_CVC1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0034)) ++#define IFXMIPS_MPS_CVC2SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0038)) ++#define IFXMIPS_MPS_CVC3SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x003C)) ++#define IFXMIPS_MPS_RAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0040)) ++#define IFXMIPS_MPS_RAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0044)) ++#define IFXMIPS_MPS_SAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0048)) ++#define IFXMIPS_MPS_SAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x004C)) ++#define IFXMIPS_MPS_CAD0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0050)) ++#define IFXMIPS_MPS_CAD1SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0054)) ++#define IFXMIPS_MPS_AD0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0058)) ++#define IFXMIPS_MPS_AD1ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x005C)) ++ ++#define IFXMIPS_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) ++#define IFXMIPS_MPS_CHIPID_VERSION_SET(value) ((((1 << 4) - 1) & (value)) << 28) ++#define IFXMIPS_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) ++#define IFXMIPS_MPS_CHIPID_PARTNUM_SET(value) ((((1 << 16) - 1) & (value)) << 12) ++#define IFXMIPS_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) ++#define IFXMIPS_MPS_CHIPID_MANID_SET(value) ((((1 << 10) - 1) & (value)) << 1) ++#else ++# include <asm/ifx/ifx_regs.h> ++# include <asm/ifx_vpe.h> ++#endif ++/* MPS register */ ++# define IFX_MPS_AD0ENR IFXMIPS_MPS_AD0ENR ++# define IFX_MPS_AD1ENR IFXMIPS_MPS_AD1ENR ++# define IFX_MPS_RAD0SR IFXMIPS_MPS_RAD0SR ++# define IFX_MPS_RAD1SR IFXMIPS_MPS_RAD1SR ++# define IFX_MPS_VC0ENR IFXMIPS_MPS_VC0ENR ++# define IFX_MPS_RVC0SR IFXMIPS_MPS_RVC0SR ++# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR ++# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR ++# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR ++# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR ++# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR ++# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR ++# define IFX_MPS_SAD0SR IFXMIPS_MPS_SAD0SR ++/* interrupt vectors */ ++# define INT_NUM_IM4_IRL14 (INT_NUM_IM4_IRL0 + 14) ++# define INT_NUM_IM4_IRL18 (INT_NUM_IM4_IRL0 + 18) ++# define INT_NUM_IM4_IRL19 (INT_NUM_IM4_IRL0 + 19) ++# define IFX_ICU_IM4_IER IFXMIPS_ICU_IM4_IER + + /* ============================= */ + /* MPS Common defines */ +@@ -26,32 +76,28 @@ + #define MPS_BASEADDRESS 0xBF107000 + #define MPS_RAD0SR MPS_BASEADDRESS + 0x0004 + +-#define MPS_RAD0SR_DU (1<<0) +-#define MPS_RAD0SR_CU (1<<1) +- + #define MBX_BASEADDRESS 0xBF200000 + #define VCPU_BASEADDRESS 0xBF208000 /* 0xBF108000 */ + /*---------------------------------------------------------------------------*/ ++#if !defined(CONFIG_LANTIQ) ++/* enabling interrupts is done with request_irq by the BSP ++ The related code should not be needed anymore */ + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + /* TODO: doublecheck - IM4 or different! */ + #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) |= X; + #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) &= ~X; +-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_ISR) = X; +-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IRSR) = X;/* |= ? */ + #else /* Danube */ + /* TODO: possibly needs to be changed to IM4 !!!!!! */ + #ifdef LINUX_2_6 + #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) |= X; + #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IER) &= ~X; +-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_ISR) = X; +-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) IFX_ICU_IM4_IRSR) = X;/* |= ? */ + #else /* */ + #define MPS_INTERRUPTS_ENABLE(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IER) |= X; + #define MPS_INTERRUPTS_DISABLE(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IER) &= ~X; +-#define MPS_INTERRUPTS_CLEAR(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_ISR) = X; +-#define MPS_INTERRUPTS_SET(X) *((volatile IFX_uint32_t*) DANUBE_ICU_IM5_IRSR) = X;/* |= ? */ + #endif /* LINUX_2_6 */ + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ ++#endif /* !defined(CONFIG_LANTIQ) */ ++ + /*---------------------------------------------------------------------------*/ + + /*---------------------------------------------------------------------------*/ +@@ -142,53 +188,9 @@ + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + /* ***** Amazon-S specific defines ***** */ + #define IFX_MPS_Base AMAZON_S_MPS +- +-//#define IFX_MPS_CHIPID AMAZON_S_MPS_CHIPID +-//#define IFX_MPS_CHIPID_VERSION_GET AMAZON_S_MPS_CHIPID_VERSION_GET +- +-//#define IFX_MPS_AD0ENR AMAZON_S_MPS_AD0ENR +-//#define IFX_MPS_AD1ENR AMAZON_S_MPS_AD1ENR +-//#define IFX_MPS_VC0ENR AMAZON_S_MPS_VC0ENR +-//#define IFX_MPS_SAD0SR AMAZON_S_MPS_SAD0SR +-//#define IFX_MPS_RAD0SR AMAZON_S_MPS_RAD0SR +-//#define IFX_MPS_CAD0SR AMAZON_S_MPS_CAD0SR +-//#define IFX_MPS_RAD1SR AMAZON_S_MPS_RAD1SR +-//#define IFX_MPS_CAD1SR AMAZON_S_MPS_CAD1SR +-//#define IFX_MPS_RVC0SR AMAZON_S_MPS_RVC0SR +-//#define IFX_MPS_CVC0SR AMAZON_S_MPS_CVC0SR +-//#define IFX_MPS_CVC1SR AMAZON_S_MPS_CVC1SR +-//#define IFX_MPS_CVC2SR AMAZON_S_MPS_CVC2SR +-//#define IFX_MPS_CVC3SR AMAZON_S_MPS_CVC3SR +- +-//#define IFX_MPS_SRAM AMAZON_S_MPS_SRAM + #else /* */ + /* ***** DANUBE specific defines ***** */ + #define IFX_MPS_Base DANUBE_MPS +- +-//#define IFX_MPS_CHIPID DANUBE_MPS_CHIPID +-//#define IFX_MPS_CHIPID_VERSION_GET DANUBE_MPS_CHIPID_VERSION_GET +-//#define IFX_MPS_CHIPID_VERSION_SET DANUBE_MPS_CHIPID_VERSION_SET +-//#define IFX_MPS_CHIPID_PARTNUM_GET DANUBE_MPS_CHIPID_PARTNUM_GET +-//#define IFX_MPS_CHIPID_PARTNUM_SET DANUBE_MPS_CHIPID_PARTNUM_SET +-//#define IFX_MPS_CHIPID_MANID_GET DANUBE_MPS_CHIPID_MANID_GET +-//#define IFX_MPS_CHIPID_MANID_SET DANUBE_MPS_CHIPID_MANID_SET +-//#define IFX_MPS_SUBVER DANUBE_MPS_SUBVER +- +-//#define IFX_MPS_AD0ENR DANUBE_MPS_AD0ENR +-//#define IFX_MPS_AD1ENR DANUBE_MPS_AD1ENR +-//#define IFX_MPS_VC0ENR DANUBE_MPS_VC0ENR +-//#define IFX_MPS_SAD0SR DANUBE_MPS_SAD0SR +-//#define IFX_MPS_RAD0SR DANUBE_MPS_RAD0SR +-//#define IFX_MPS_CAD0SR DANUBE_MPS_CAD0SR +-//#define IFX_MPS_RAD1SR DANUBE_MPS_RAD1SR +-//#define IFX_MPS_CAD1SR DANUBE_MPS_CAD1SR +-//#define IFX_MPS_RVC0SR DANUBE_MPS_RVC0SR +-//#define IFX_MPS_CVC0SR DANUBE_MPS_CVC0SR +-//#define IFX_MPS_CVC1SR DANUBE_MPS_CVC1SR +-//#define IFX_MPS_CVC2SR DANUBE_MPS_CVC2SR +-//#define IFX_MPS_CVC3SR DANUBE_MPS_CVC3SR +- +-//#define IFX_MPS_SRAM DANUBE_MPS_SRAM + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ + typedef enum + { +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -57,10 +57,11 @@ + #include <linux/moduleparam.h> + #endif /* */ + +- ++#if !defined CONFIG_LANTIQ + #include <asm/ifx/irq.h> + #include <asm/ifx/ifx_regs.h> + #include <asm/ifx_vpe.h> ++#endif + + /* lib_ifxos headers */ + #include "ifx_types.h" +@@ -959,7 +960,7 @@ + #endif /* MPS_FIFO_BLOCKING_WRITE */ + case FIO_MPS_GET_STATUS: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + /* get the status of the channel */ + if (!from_kernel) +@@ -993,7 +994,7 @@ + #if CONFIG_MPS_HISTORY_SIZE > 0 + case FIO_MPS_GET_CMD_HISTORY: + { +- IFX_uint32_t flags; ++ unsigned long flags; + + if (from_kernel) + { +@@ -1685,6 +1686,7 @@ + sprintf (buf + len, " minLv: \t %8d\n", + ifx_mps_dev.voice_mb[i].upstrm_fifo->min_space); + } ++ + return len; + } + +@@ -2291,9 +2293,11 @@ + return result; + } + ++#if !defined(CONFIG_LANTIQ) ++ /** \todo This is handled already with request_irq, remove */ + /* Enable all MPS Interrupts at ICU0 */ + MPS_INTERRUPTS_ENABLE (0x0000FF80); +- ++#endif + /* enable mailbox interrupts */ + ifx_mps_enable_mailbox_int (); + /* init FW ready event */ +@@ -2421,9 +2425,11 @@ + /* disable mailbox interrupts */ + ifx_mps_disable_mailbox_int (); + ++#if !defined(CONFIG_LANTIQ) + /* disable Interrupts at ICU0 */ +- MPS_INTERRUPTS_DISABLE (DANUBE_MPS_AD0_IR4); /* Disable DFE/AFE 0 Interrupts +- */ ++ /* Disable DFE/AFE 0 Interrupts*/ ++ MPS_INTERRUPTS_DISABLE (DANUBE_MPS_AD0_IR4); ++#endif + + /* disable all MPS interrupts */ + ifx_mps_disable_all_int (); +--- a/src/drv_vmmc_ioctl.c ++++ b/src/drv_vmmc_ioctl.c +@@ -18,6 +18,7 @@ + /* Includes */ + /* ============================= */ + #include "drv_api.h" ++#include "drv_vmmc_init.h" + #include "drv_vmmc_api.h" + #include "drv_vmmc_bbd.h" + diff --git a/package/system/ltq-vmmc/patches/400-falcon.patch b/package/system/ltq-vmmc/patches/400-falcon.patch new file mode 100644 index 0000000000..490d6e5dc9 --- /dev/null +++ b/package/system/ltq-vmmc/patches/400-falcon.patch @@ -0,0 +1,968 @@ +--- a/configure.in ++++ b/configure.in +@@ -956,14 +956,15 @@ AC_DEFINE([VMMC],[1],[enable VMMC suppor + AM_CONDITIONAL(DANUBE, false) + AM_CONDITIONAL(AR9, false) + AM_CONDITIONAL(VR9, false) ++AM_CONDITIONAL(FALCON, false) + AC_ARG_WITH(device, + AC_HELP_STRING( +- [--with-device=DANUBE|TWINPASS|AR9|VR9], ++ [--with-device=DANUBE|TWINPASS|AR9|VR9|FALCON], + [Set device type, default is DANUBE] + ), + [ + if test "$withval" = yes; then +- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]); ++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]); + else + case $withval in + DANUBE) +@@ -986,8 +987,13 @@ AC_ARG_WITH(device, + AC_DEFINE([SYSTEM_VR9],[1],[enable VR9 specific code]) + AM_CONDITIONAL(VR9, true) + ;; ++ FALCON) ++ AC_MSG_RESULT(FALCON device is used); ++ AC_DEFINE([SYSTEM_FALCON],[1],[enable FALCON specific code]) ++ AM_CONDITIONAL(FALCON, true) ++ ;; + *) +- AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9]); ++ AC_MSG_ERROR([Set device type! Valid choices are DANUBE|TWINPASS|AR9|VR9|FALCON]); + ;; + esac + fi +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -70,6 +70,11 @@ drv_vmmc_SOURCES +=\ + mps/drv_mps_vmmc_ar9.c + endif + ++if FALCON ++drv_vmmc_SOURCES +=\ ++ mps/drv_mps_vmmc_falcon.c ++endif ++ + endif + + if PMC_SUPPORT +--- a/drv_version.h ++++ b/drv_version.h +@@ -36,6 +36,10 @@ + #define MIN_FW_MAJORSTEP 2 + #define MIN_FW_MINORSTEP 1 + #define MIN_FW_HOTFIXSTEP 0 ++#elif defined(SYSTEM_FALCON) ++#define MIN_FW_MAJORSTEP 0 ++#define MIN_FW_MINORSTEP 1 ++#define MIN_FW_HOTFIXSTEP 0 + #else + #error unknown system + #endif +--- a/src/drv_vmmc_bbd.c ++++ b/src/drv_vmmc_bbd.c +@@ -34,6 +34,7 @@ + #define VMMC_WL_SDD_BASIC_CFG 0x04000400 + #define VMMC_WL_SDD_RING_CFG 0x04000500 + #define VMMC_WL_SDD_DCDC_CFG 0x04000C00 ++#define VMMC_WL_SDD_MWI_CFG 0x04000600 + + #define IDLE_EXT_TOGGLE_SLEEP_MS 5 + +@@ -52,6 +53,8 @@ + #define BBD_VMMC_MAGIC 0x41523921 /* "AR9" */ + #elif defined(SYSTEM_VR9) + #define BBD_VMMC_MAGIC 0x56523921 /* "VR9" */ ++#elif defined(SYSTEM_FALCON) ++#define BBD_VMMC_MAGIC 0x46414C43 /* "FALC" */ + #else + #error system undefined + #endif +@@ -525,9 +528,6 @@ static IFX_int32_t VMMC_BBD_BlockHandler + IFX_uint16_t slic_val; + IFX_int32_t ret = IFX_SUCCESS; + +- TRACE(VMMC, DBG_LEVEL_LOW, +- ("bbd block with tag 0x%04X passed\n", pBBDblock->tag)); +- + /* for FXO line allowed blocks are FXO_CRAM and TRANSPARENT */ + if (pCh->pALM->line_type_fxs != IFX_TRUE) + { +@@ -686,6 +686,7 @@ static IFX_int32_t VMMC_BBD_BlockHandler + break; + } + } /* if */ ++ + return ret; + } + +@@ -1026,6 +1027,7 @@ static IFX_int32_t vmmc_BBD_WhiteListedC + } + case VMMC_WL_SDD_RING_CFG: + case VMMC_WL_SDD_DCDC_CFG: ++ case VMMC_WL_SDD_MWI_CFG: + ret = CmdWrite (pCh->pParent, Msg.val, Msg.cmd.LENGTH); + break; + +@@ -1068,7 +1070,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + IFX_uint32_t countWords; + IFX_uint32_t posBytes = 0; + IFX_uint8_t lenBytes, *pByte; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint8_t padBytes = 0; + #endif + IFX_uint16_t cram_offset, cram_crc, +@@ -1088,7 +1090,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + #ifdef SYSTEM_DANUBE + /* CMD1 is a COP command */ + pCmd[0] = (0x0200) | (pCh->nChannel - 1); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* SDD_Coef command */ + pCmd[0] = (0x0400) | (pCh->nChannel - 1); + pCmd[1] = (0x0D00); +@@ -1111,7 +1113,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + pCmd[1] = ((cram_offset + (posBytes >> 1)) << 8); + /* set CRAM data while taking care of endianess */ + cpb2w (&pCmd[2], &pByte[posBytes], lenBytes); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* calculate length to download (in words = 16bit), + maximum allowed length for this message is 56 Bytes = 28 Words */ + if (countWords > ((MAX_CMD_WORD - CMD_HDR_CNT - 1))) +@@ -1140,7 +1142,7 @@ static IFX_int32_t vmmc_BBD_DownloadChCr + /* write Data */ + #if defined SYSTEM_DANUBE + ret = CmdWrite (pCh->pParent, (IFX_uint32_t *) pCmd, lenBytes); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + #if 1 + /* lenBytes + 2 bytes for block offset/length which are not calculated + in the download progress */ +--- a/src/mps/drv_mps_version.h ++++ b/src/mps/drv_mps_version.h +@@ -17,7 +17,7 @@ + #define VERSIONSTEP 2 + #define VERS_TYPE 5 + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + #define IFX_MPS_PLATFORM_NAME "MIPS34KEc" + #elif defined(SYSTEM_DANUBE) + #define IFX_MPS_PLATFORM_NAME "MIPS24KEc" +--- a/src/mps/drv_mps_vmmc_linux.c ++++ b/src/mps/drv_mps_vmmc_linux.c +@@ -2225,7 +2225,7 @@ IFX_int32_t __init ifx_mps_init_module ( + #if defined(CONFIG_MIPS) && !defined(CONFIG_MIPS_UNCACHED) + #if defined(SYSTEM_DANUBE) + bDoCacheOps = IFX_TRUE; /* on Danube always perform cache ops */ +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* on AR9/VR9 cache is configured by BSP; + here we check whether the D-cache is shared or partitioned; + 1) in case of shared D-cache all cache operations are omitted; +@@ -2255,7 +2255,8 @@ IFX_int32_t __init ifx_mps_init_module ( + + /* reset the device before initializing the device driver */ + ifx_mps_reset (); +- result = request_irq (INT_NUM_IM4_IRL18, ++ ++ result = request_irq (INT_NUM_IM4_IRL18, + #ifdef LINUX_2_6 + ifx_mps_ad0_irq, IRQF_DISABLED + #else /* */ +@@ -2396,7 +2397,7 @@ IFX_int32_t __init ifx_mps_init_module ( + if (result = ifx_mps_init_gpt_danube ()) + return result; + #endif /*DANUBE*/ +- TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n")); ++ TRACE (MPS, DBG_LEVEL_HIGH, ("Downloading Firmware...\n")); + ifx_mps_download_firmware (IFX_NULL, (mps_fw *) 0xa0a00000); + udelay (500); + TRACE (MPS, DBG_LEVEL_HIGH, ("Providing Buffers...\n")); +--- /dev/null ++++ b/src/mps/drv_mps_vmmc_falcon.c +@@ -0,0 +1,463 @@ ++/****************************************************************************** ++ ++ Copyright (c) 2009 ++ Lantiq Deutschland GmbH ++ Am Campeon 3; 85579 Neubiberg, Germany ++ ++ For licensing information, see the file 'LICENSE' in the root folder of ++ this software module. ++ ++**************************************************************************** ++ Module : drv_mps_vmmc_falcon.c ++ Description : This file contains the implementation of the FALC-ON specific ++ driver functions. ++*******************************************************************************/ ++ ++/* ============================= */ ++/* Includes */ ++/* ============================= */ ++#include "drv_config.h" ++ ++#if defined(SYSTEM_FALCON) /* defined in drv_config.h */ ++ ++/* lib_ifxos headers */ ++#include "ifx_types.h" ++#include "ifxos_linux_drv.h" ++#include "ifxos_copy_user_space.h" ++#include "ifxos_event.h" ++#include "ifxos_lock.h" ++#include "ifxos_select.h" ++#include "ifxos_interrupt.h" ++#include <linux/gpio.h> ++#include <sys1_reg.h> ++#include <falcon.h> ++#include <falcon_irq.h> ++#include <vpe.h> ++#include <sysctrl.h> ++void (*ifx_bsp_basic_mps_decrypt)(unsigned int addr, int n) = (void (*)(unsigned int, int))0xbf000290; ++ ++#define IFX_MPS_SRAM IFXMIPS_MPS_SRAM ++ ++/*#define USE_PLAIN_VOICE_FIRMWARE*/ ++/* board specific headers */ ++ ++/* device specific headers */ ++#include "drv_mps_vmmc.h" ++#include "drv_mps_vmmc_dbg.h" ++#include "drv_mps_vmmc_device.h" ++ ++/* ============================= */ ++/* Local Macros & Definitions */ ++/* ============================= */ ++/* Firmware watchdog timer counter address */ ++#define VPE1_WDOG_CTR_ADDR ((IFX_uint32_t)((IFX_uint8_t* )IFX_MPS_SRAM + 432)) ++ ++/* Firmware watchdog timeout range, values in ms */ ++#define VPE1_WDOG_TMOUT_MIN 20 ++#define VPE1_WDOG_TMOUT_MAX 5000 ++ ++/* ============================= */ ++/* Global variable definition */ ++/* ============================= */ ++extern mps_comm_dev *pMPSDev; ++ ++/* ============================= */ ++/* Global function declaration */ ++/* ============================= */ ++IFX_void_t ifx_mps_release (IFX_void_t); ++extern IFX_uint32_t ifx_mps_reset_structures (mps_comm_dev * pMPSDev); ++extern IFX_int32_t ifx_mps_bufman_close (IFX_void_t); ++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count); ++extern IFXOS_event_t fw_ready_evt; ++/* ============================= */ ++/* Local function declaration */ ++/* ============================= */ ++static IFX_int32_t ifx_mps_fw_wdog_start_ar9(IFX_void_t); ++ ++/* ============================= */ ++/* Local variable definition */ ++/* ============================= */ ++static IFX_int32_t vpe1_started = 0; ++/* VMMC watchdog timer callback */ ++IFX_int32_t (*ifx_wdog_callback) (IFX_uint32_t flags) = IFX_NULL; ++ ++/* ============================= */ ++/* Local function definition */ ++/* ============================= */ ++ ++/****************************************************************************** ++ * AR9 Specific Routines ++ ******************************************************************************/ ++ ++/** ++ * Start AR9 EDSP firmware watchdog mechanism. ++ * Called after download and startup of VPE1. ++ * ++ * \param none ++ * \return 0 IFX_SUCCESS ++ * \return -1 IFX_ERROR ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_fw_wdog_start_ar9() ++{ ++ return IFX_SUCCESS; ++} ++ ++/** ++ * Firmware download to Voice CPU ++ * This function performs a firmware download to the coprocessor. ++ * ++ * \param pMBDev Pointer to mailbox device structure ++ * \param pFWDwnld Pointer to firmware structure ++ * \return 0 IFX_SUCCESS, firmware ready ++ * \return -1 IFX_ERROR, firmware not downloaded. ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_download_firmware (mps_mbx_dev *pMBDev, mps_fw *pFWDwnld) ++{ ++ IFX_uint32_t mem, cksum; ++ IFX_uint8_t crc; ++ IFX_boolean_t bMemReqNotPresent = IFX_FALSE; ++ ++ /* VCC register */ ++ /* dummy accesss on GTC for GPONC-55, otherwise upper bits are random on read */ ++ ltq_r32 ((u32 *)((KSEG1 | 0x1DC000B0))); ++ /* NTR Frequency Select 1536 kHz per default or take existing, ++ NTR Output Enable and NTR8K Output Enable */ ++ if ((ltq_r32 ((u32 *)(GPON_SYS_BASE + 0xBC)) & 7) == 0) ++ ltq_w32_mask (0x10187, 0x183, (u32 *)(GPON_SYS_BASE + 0xBC)); ++ else ++ ltq_w32_mask (0x10180, 0x180, (u32 *)(GPON_SYS_BASE + 0xBC)); ++#if 0 ++ /* BIU-ICU1-IM1_ISR - IM1:FSCT_CMP1=1 and FSC_ROOT=1 ++ (0x1f880328 = 0x00002800) */ ++ ltq_w32 (0x00002800, (u32 *)(GPON_ICU1_BASE + 0x30)); ++#endif ++ /* copy FW footer from user space */ ++ if (IFX_NULL == IFXOS_CpyFromUser(pFW_img_data, ++ pFWDwnld->data+pFWDwnld->length/4-sizeof(*pFW_img_data)/4, ++ sizeof(*pFW_img_data))) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n", ++ __FILE__, __func__, __LINE__)); ++ return IFX_ERROR; ++ } ++ ++ mem = pFW_img_data->mem; ++ ++ /* memory requirement sanity check */ ++ if ((crc = ~((mem >> 16) + (mem >> 8) + mem)) != (mem >> 24)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: warning, image does not contain size - assuming 1MB!\n", ++ __FILE__, __func__, __LINE__)); ++ mem = 1 * 1024 * 1024; ++ bMemReqNotPresent = IFX_TRUE; ++ } ++ else ++ { ++ mem &= 0x00FFFFFF; ++ } ++ ++ /* check if FW image fits in available memory space */ ++ if (mem > vpe1_get_max_mem(0)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("[%s %s %d]: error, firmware memory exceeds reserved space (%i > %i)!\n", ++ __FILE__, __func__, __LINE__, mem, vpe1_get_max_mem(0))); ++ return IFX_ERROR; ++ } ++ ++ /* reset the driver */ ++ ifx_mps_reset (); ++ ++ /* call BSP to get cpu1 base address */ ++ cpu1_base_addr = (IFX_uint32_t *)vpe1_get_load_addr(0); ++ ++ /* check if CPU1 base address is sane ++ \todo: check if address is 1MB aligned, ++ also make it visible in a /proc fs */ ++ if (!cpu1_base_addr) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "IFX_MPS: CPU1 base address is invalid!\r\n")); ++ return IFX_ERROR; ++ } ++ /* further use uncached value */ ++ cpu1_base_addr = (IFX_uint32_t *)KSEG1ADDR(cpu1_base_addr); ++ ++ /* free all data buffers that might be currently used by FW */ ++ if (IFX_NULL != ifx_mps_bufman_freeall) ++ { ++ ifx_mps_bufman_freeall(); ++ } ++ ++ if(FW_FORMAT_NEW) ++ { ++ /* adjust download length */ ++ pFWDwnld->length -= (sizeof(*pFW_img_data)-sizeof(IFX_uint32_t)); ++ } ++ else ++ { ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ ++ /* handle unlikely case if FW image does not contain memory requirement - ++ assumed for old format only */ ++ if (IFX_TRUE == bMemReqNotPresent) ++ pFWDwnld->length += sizeof(IFX_uint32_t); ++ ++ /* in case of old FW format always assume that FW is encrypted; ++ use compile switch USE_PLAIN_VOICE_FIRMWARE for plain FW */ ++#ifndef USE_PLAIN_VOICE_FIRMWARE ++ pFW_img_data->enc = 1; ++#else ++#warning Using unencrypted firmware! ++ pFW_img_data->enc = 0; ++#endif /* USE_PLAIN_VOICE_FIRMWARE */ ++ /* initializations for the old format */ ++ pFW_img_data->st_addr_crc = 2*sizeof(IFX_uint32_t) + ++ FW_AR9_OLD_FMT_XCPT_AREA_SZ; ++ pFW_img_data->en_addr_crc = pFWDwnld->length; ++ pFW_img_data->fw_vers = 0; ++ pFW_img_data->magic = 0; ++ } ++ ++ /* copy FW image to base address of CPU1 */ ++ if (IFX_NULL == ++ IFXOS_CpyFromUser ((IFX_void_t *)cpu1_base_addr, ++ (IFX_void_t *)pFWDwnld->data, pFWDwnld->length)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: copy_from_user error\r\n", __FILE__, ++ __func__, __LINE__)); ++ return IFX_ERROR; ++ } ++ ++ /* process firmware decryption */ ++ if (pFW_img_data->enc == 1) ++ { ++ if(FW_FORMAT_NEW) ++ { ++ /* adjust decryption length (avoid decrypting CRC32 checksum) */ ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ } ++ /* BootROM actually decrypts n+4 bytes if n bytes were passed for ++ decryption. Subtract sizeof(u32) from length to avoid decryption ++ of data beyond the FW image code */ ++ pFWDwnld->length -= sizeof(IFX_uint32_t); ++ ifx_bsp_basic_mps_decrypt((unsigned int)cpu1_base_addr, pFWDwnld->length); ++ } ++ ++ /* calculate CRC32 checksum over downloaded image */ ++ cksum = ifx_mps_fw_crc32(cpu1_base_addr, pFW_img_data); ++ ++ /* verify the checksum */ ++ if(FW_FORMAT_NEW) ++ { ++ if (cksum != pFW_img_data->crc32) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("MPS: FW checksum error: img=0x%08x calc=0x%08x\r\n", ++ pFW_img_data->crc32, cksum)); ++ /*return IFX_ERROR;*/ ++ } ++ } ++ else ++ { ++ /* just store self-calculated checksum */ ++ pFW_img_data->crc32 = cksum; ++ } ++ ++ /* start VPE1 */ ++ ifx_mps_release (); ++#if 0 ++ /* start FW watchdog mechanism */ ++ ifx_mps_fw_wdog_start_ar9(); ++#endif ++ /* get FW version */ ++ return ifx_mps_get_fw_version (0); ++} ++ ++ ++/** ++ * Restart CPU1 ++ * This function restarts CPU1 by accessing the reset request register and ++ * reinitializes the mailbox. ++ * ++ * \return 0 IFX_SUCCESS, successful restart ++ * \return -1 IFX_ERROR, if reset failed ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_restart (IFX_void_t) ++{ ++ /* raise reset request for CPU1 and reset driver structures */ ++ ifx_mps_reset (); ++ /* Disable GPTC Interrupt to CPU1 */ ++ ifx_mps_shutdown_gpt (); ++ /* re-configure GPTC */ ++ ifx_mps_init_gpt (); ++ /* let CPU1 run */ ++ ifx_mps_release (); ++ /* start FW watchdog mechanism */ ++ ifx_mps_fw_wdog_start_ar9(); ++ TRACE (MPS, DBG_LEVEL_HIGH, ("IFX_MPS: Restarting firmware...")); ++ return ifx_mps_get_fw_version (0); ++} ++ ++/** ++ * Shutdown MPS - stop VPE1 ++ * This function stops VPE1 ++ * ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_shutdown (IFX_void_t) ++{ ++ if (vpe1_started) ++ { ++ /* stop software watchdog timer */ ++ vpe1_sw_wdog_stop (0); ++ /* clean up the BSP callback function */ ++ vpe1_sw_wdog_register_reset_handler (IFX_NULL); ++ /* stop VPE1 */ ++ vpe1_sw_stop (0); ++ vpe1_started = 0; ++ } ++ /* free GPTC */ ++ ifx_mps_shutdown_gpt (); ++} ++ ++/** ++ * Reset CPU1 ++ * This function causes a reset of CPU1 by clearing the CPU0 boot ready bit ++ * in the reset request register RCU_RST_REQ. ++ * It does not change the boot configuration registers for CPU0 or CPU1. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_reset (IFX_void_t) ++{ ++ /* if VPE1 is already started, stop it */ ++ if (vpe1_started) ++ { ++ /* stop software watchdog timer first */ ++ vpe1_sw_wdog_stop (0); ++ vpe1_sw_stop (0); ++ vpe1_started = 0; ++ } ++ ++ /* reset driver */ ++ ifx_mps_reset_structures (pMPSDev); ++ ifx_mps_bufman_close (); ++ return; ++} ++ ++/** ++ * Let CPU1 run ++ * This function starts VPE1 ++ * ++ * \return none ++ * \ingroup Internal ++ */ ++IFX_void_t ifx_mps_release (IFX_void_t) ++{ ++ IFX_int_t ret; ++ IFX_int32_t RetCode = 0; ++ ++ /* Start VPE1 */ ++ if (IFX_SUCCESS != ++ vpe1_sw_start ((IFX_void_t *)cpu1_base_addr, 0, 0)) ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, (KERN_ERR "Error starting VPE1\r\n")); ++ return; ++ } ++ vpe1_started = 1; ++ ++ /* sleep 3 seconds until FW is ready */ ++ ret = IFXOS_EventWait (&fw_ready_evt, 3000, &RetCode); ++ if ((ret == IFX_ERROR) && (RetCode == 1)) ++ { ++ /* timeout */ ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_ERR "[%s %s %d]: Timeout waiting for firmware ready.\r\n", ++ __FILE__, __func__, __LINE__)); ++ /* recalculate and compare the firmware checksum */ ++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data); ++ /* dump exception area on a console */ ++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data); ++ } ++} ++ ++/** ++ * WDT callback. ++ * This function is called by BSP (module softdog_vpe) in case if software ++ * watchdog timer expiration is detected by BSP. ++ * This function needs to be registered at BSP as WDT callback using ++ * vpe1_sw_wdog_register_reset_handler() API. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_int32_t ifx_mps_wdog_callback (IFX_uint32_t wdog_cleared_ok_count) ++{ ++#ifdef DEBUG ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ ("MPS: watchdog callback! arg=0x%08x\r\n", wdog_cleared_ok_count)); ++#endif /* DEBUG */ ++ ++ /* reset SmartSLIC is done by FW */ ++ /* recalculate and compare the firmware checksum */ ++ ifx_mps_fw_crc_compare(cpu1_base_addr, pFW_img_data); ++ ++ /* dump exception area on a console */ ++ ifx_mps_dump_fw_xcpt(cpu1_base_addr, pFW_img_data); ++ ++ if (IFX_NULL != ifx_wdog_callback) ++ { ++ /* call VMMC driver */ ++ ifx_wdog_callback (wdog_cleared_ok_count); ++ } ++ else ++ { ++ TRACE (MPS, DBG_LEVEL_HIGH, ++ (KERN_WARNING "MPS: VMMC watchdog timer callback is NULL.\r\n")); ++ } ++ return 0; ++} ++ ++/** ++ * Register WDT callback. ++ * This function is called by VMMC driver to register its callback in ++ * the MPS driver. ++ * ++ * \return 0 IFX_SUCCESS, cannot fail ++ * \ingroup Internal ++ */ ++IFX_int32_t ++ifx_mps_register_wdog_callback (IFX_int32_t (*pfn) (IFX_uint32_t flags)) ++{ ++ ifx_wdog_callback = pfn; ++ return 0; ++} ++ ++/** ++ Hardware setup on FALC ON ++*/ ++void sys_hw_setup (void) ++{ ++ /* Set INFRAC register bit 1: clock enable of the GPE primary clock. */ ++ sys_gpe_hw_activate (0); ++ /* enable 1.5 V */ ++ ltq_w32_mask (0xf, 0x0b, (u32 *)(GPON_SYS1_BASE | 0xbc)); ++ /* SYS1-CLKEN:GPTC = 1 and MPS, no longer FSCT = 1 */ ++ sys1_hw_activate (ACTS_MPS | ACTS_GPTC); ++ /* GPTC:CLC:RMC = 1 */ ++ ltq_w32 (0x00000100, (u32 *)(KSEG1 | 0x1E100E00)); ++} ++ ++#ifndef VMMC_WITH_MPS ++EXPORT_SYMBOL (ifx_mps_register_wdog_callback); ++#endif /* !VMMC_WITH_MPS */ ++ ++#endif /* SYSTEM_FALCON */ +--- a/src/mps/drv_mps_vmmc_common.c ++++ b/src/mps/drv_mps_vmmc_common.c +@@ -66,6 +66,10 @@ static void inline bsp_mask_and_ack_irq( + # include <asm/ifx/ifx_regs.h> + # include <asm/ifx/ifx_gptu.h> + #endif ++#if defined(SYSTEM_FALCON) ++#include <sys1_reg.h> ++#include <sysctrl.h> ++#endif + + #include "drv_mps_vmmc.h" + #include "drv_mps_vmmc_dbg.h" +@@ -1156,7 +1160,12 @@ IFX_uint32_t ifx_mps_init_structures (mp + mailbox, * upstream and downstream direction. */ + memset ( + /* avoid to overwrite CPU boot registers */ ++#if defined(SYSTEM_FALCON) ++ (IFX_void_t *) MBX_Memory + ++ 2 * sizeof (mps_boot_cfg_reg), ++#else + (IFX_void_t *) MBX_Memory, ++#endif + 0, + sizeof (mps_mbx_reg) - 2 * sizeof (mps_boot_cfg_reg)); + MBX_Memory->MBX_UPSTR_CMD_BASE = +@@ -2651,7 +2660,6 @@ IFX_void_t ifx_mps_enable_mailbox_int () + #endif + + *IFX_MPS_AD0ENR = Ad0Reg.val; +- + } + + /** +@@ -2669,6 +2677,7 @@ IFX_void_t ifx_mps_disable_mailbox_int ( + Ad0Reg.fld.cu_mbx = 0; + Ad0Reg.fld.du_mbx = 0; + *IFX_MPS_AD0ENR = Ad0Reg.val; ++ + } + + /** +@@ -2766,11 +2775,13 @@ irqreturn_t ifx_mps_ad0_irq (IFX_int32_t + /* handle only enabled interrupts */ + MPS_Ad0StatusReg.val &= *IFX_MPS_AD0ENR; + ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + /* FW is up and ready to process commands */ + if (MPS_Ad0StatusReg.fld.dl_end) + { +@@ -2919,11 +2930,13 @@ irqreturn_t ifx_mps_ad1_irq (IFX_int32_t + /* handle only enabled interrupts */ + MPS_Ad1StatusReg.val &= *IFX_MPS_AD1ENR; + ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + pMPSDev->event.MPS_Ad1Reg.val = MPS_Ad1StatusReg.val; + + /* use callback function or queue wake up to notify about data reception */ +@@ -2977,11 +2990,13 @@ irqreturn_t ifx_mps_vc_irq (IFX_int32_t + IFX_MPS_CVC0SR[chan] = MPS_VCStatusReg.val; + /* handle only enabled interrupts */ + MPS_VCStatusReg.val &= IFX_MPS_VC0ENR[chan]; ++#if !defined(SYSTEM_FALCON) + #ifdef LINUX_2_6 + bsp_mask_and_ack_irq (irq); + #else /* */ + mask_and_ack_danube_irq (irq); + #endif /* */ ++#endif /* !defined(SYSTEM_FALCON) */ + + pMPSDev->event.MPS_VCStatReg[chan].val = MPS_VCStatusReg.val; + #ifdef PRINT_ON_ERR_INTERRUPT +@@ -3126,6 +3141,7 @@ IFX_int32_t ifx_mps_get_fw_version (IFX_ + */ + IFX_return_t ifx_mps_init_gpt () + { ++#if !defined(SYSTEM_FALCON) + unsigned long flags; + IFX_uint32_t timer_flags, timer, loops = 0; + IFX_ulong_t count; +@@ -3134,7 +3150,11 @@ IFX_return_t ifx_mps_init_gpt () + #else /* Danube */ + timer = TIMER1B; + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ ++#endif + ++#if defined(SYSTEM_FALCON) ++ sys_hw_setup (); ++#else + /* calibration loop - required to syncronize GPTC interrupt with falling + edge of FSC clock */ + timer_flags = +@@ -3179,7 +3199,7 @@ Probably already in use.\r\n", __FILE__, + #endif /* DEBUG */ + + IFXOS_UNLOCKINT (flags); +- ++#endif + return IFX_SUCCESS; + } + +@@ -3194,6 +3214,9 @@ Probably already in use.\r\n", __FILE__, + */ + IFX_void_t ifx_mps_shutdown_gpt (IFX_void_t) + { ++#if defined(SYSTEM_FALCON) ++ sys1_hw_deactivate (ACTS_MPS); ++#else + IFX_uint32_t timer; + #if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) + timer = TIMER1A; +@@ -3202,6 +3225,7 @@ IFX_void_t ifx_mps_shutdown_gpt (IFX_voi + #endif /* SYSTEM_AR9 || SYSTEM_VR9 */ + + ifx_gptu_timer_free (timer); ++#endif + } + + /** +--- a/src/mps/drv_mps_vmmc_device.h ++++ b/src/mps/drv_mps_vmmc_device.h +@@ -22,7 +22,12 @@ + # include <lantiq_soc.h> + # include <gpio.h> + #define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000)) ++#if defined(SYSTEM_FALCON) ++#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1D004000) ++#else + #define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000) ++#endif ++ + #define IFXMIPS_MPS_CHIPID ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0344)) + #define IFXMIPS_MPS_VC0ENR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0000)) + #define IFXMIPS_MPS_RVC0SR ((u32 *)(IFXMIPS_MPS_BASE_ADDR + 0x0010)) +@@ -73,10 +78,11 @@ + /* MPS Common defines */ + /* ============================= */ + +-#define MPS_BASEADDRESS 0xBF107000 +-#define MPS_RAD0SR MPS_BASEADDRESS + 0x0004 +- ++#if defined(SYSTEM_FALCON) ++#define MBX_BASEADDRESS 0xBF200040 ++#else + #define MBX_BASEADDRESS 0xBF200000 ++#endif + #define VCPU_BASEADDRESS 0xBF208000 /* 0xBF108000 */ + /*---------------------------------------------------------------------------*/ + #if !defined(CONFIG_LANTIQ) +@@ -118,7 +124,6 @@ + /*---------------------------------------------------------------------------*/ + + #ifdef CONFIG_MPS_EVENT_MBX +- + #define MBX_CMD_FIFO_SIZE 64 /**< Size of command FIFO in bytes */ + #define MBX_DATA_UPSTRM_FIFO_SIZE 64 + #define MBX_DATA_DNSTRM_FIFO_SIZE 128 +@@ -294,6 +299,10 @@ typedef struct + #ifdef CONFIG_MPS_EVENT_MBX + typedef struct + { ++#if defined(SYSTEM_FALCON) ++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ ++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */ + volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */ + volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */ +@@ -317,13 +326,19 @@ typedef struct + volatile IFX_uint32_t MBX_UPSTR_EVENT_WRITE; /**< Upstream Event FIFO Write Index */ + volatile IFX_uint32_t MBX_EVENT[MBX_EVENT_DATA_WORDS]; + volatile IFX_uint32_t reserved[4]; ++#if !defined(SYSTEM_FALCON) + mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ + mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + } mps_mbx_reg; + + #else /* */ + typedef struct + { ++#if defined(SYSTEM_FALCON) ++ mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ ++ mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + volatile IFX_uint32_t *MBX_UPSTR_CMD_BASE; /**< Upstream Command FIFO Base Address */ + volatile IFX_uint32_t MBX_UPSTR_CMD_SIZE; /**< Upstream Command FIFO size in byte */ + volatile IFX_uint32_t *MBX_DNSTR_CMD_BASE; /**< Downstream Command FIFO Base Address */ +@@ -341,8 +356,10 @@ typedef struct + volatile IFX_uint32_t MBX_DNSTR_DATA_READ; /**< Downstream Data FIFO Read Index */ + volatile IFX_uint32_t MBX_DNSTR_DATA_WRITE; /**< Downstream Data FIFO Write Index */ + volatile IFX_uint32_t MBX_DATA[MBX_DATA_WORDS]; ++#if !defined(SYSTEM_FALCON) + mps_boot_cfg_reg MBX_CPU0_BOOT_CFG; /**< CPU0 Boot Configuration */ + mps_boot_cfg_reg MBX_CPU1_BOOT_CFG; /**< CPU1 Boot Configuration */ ++#endif + } mps_mbx_reg; + #endif /* CONFIG_MPS_EVENT_MBX */ + +--- a/src/drv_api.h ++++ b/src/drv_api.h +@@ -183,7 +183,7 @@ + #endif + + /* TAPI FXS Phone Detection feature is not available for Danube platform */ +-#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9)) ++#if defined(TAPI_PHONE_DETECTION) && (defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON)) + #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION VMMC_FEAT_PHONE_DETECTION + #else + #define VMMC_CFG_ADD_FEAT_PHONE_DETECTION 0 +--- a/src/drv_vmmc_alm.c ++++ b/src/drv_vmmc_alm.c +@@ -800,7 +800,7 @@ IFX_void_t VMMC_ALM_Free_Ch_Structures ( + } + + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /** + Check whether SmartSLIC is connected + +@@ -836,7 +836,7 @@ IFX_boolean_t VMMC_ALM_SmartSLIC_IsConne + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /** + Read the number of channels on the SmartSLIC. + +@@ -1876,7 +1876,7 @@ IFX_int32_t VMMC_TAPI_LL_ALM_VMMC_Test_L + /* write updated message contents */ + ret = CmdWrite (pDev, (IFX_uint32_t *)((IFX_void_t *)&debugCfg), + DCCTL_CMD_LEN); +-#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#elif defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint32_t dcctrlLoop[2]; + IFX_uint32_t ch = (IFX_uint32_t)(pCh->nChannel - 1); + +--- a/src/drv_vmmc_alm.h ++++ b/src/drv_vmmc_alm.h +@@ -65,7 +65,7 @@ extern IFX_void_t irq_VMMC_ALM_LineDisab + extern IFX_void_t VMMC_ALM_CorrectLinemodeCache (VMMC_CHANNEL *pCh, + IFX_uint16_t lm); + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + extern IFX_boolean_t VMMC_ALM_SmartSLIC_IsConnected ( + VMMC_DEVICE *pDev); + +--- a/src/drv_vmmc_init.c ++++ b/src/drv_vmmc_init.c +@@ -52,15 +52,6 @@ + #include "ifx_pmu.h" + #endif /* PMU_SUPPORTED */ + +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) +-# define IFX_MPS_CAD0SR IFXMIPS_MPS_CAD0SR +-# define IFX_MPS_CAD1SR IFXMIPS_MPS_CAD1SR +-# define IFX_MPS_CVC0SR IFXMIPS_MPS_CVC0SR +-# define IFX_MPS_CVC1SR IFXMIPS_MPS_CVC1SR +-# define IFX_MPS_CVC2SR IFXMIPS_MPS_CVC2SR +-# define IFX_MPS_CVC3SR IFXMIPS_MPS_CVC3SR +-#endif +- + /* ============================= */ + /* Local Macros & Definitions */ + /* ============================= */ +@@ -820,7 +811,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init( + MIN_FW_HOTFIXSTEP}; + IFX_uint8_t tmp1, tmp2; + IFX_TAPI_RESOURCE nResource; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + IFX_uint8_t nChannels, nFXOChannels; + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + IFX_int32_t ret = VMMC_statusOk; +@@ -874,7 +865,7 @@ static IFX_int32_t VMMC_TAPI_LL_FW_Init( + pDev->bSmartSlic = IFX_FALSE; + pDev->bSlicSupportsIdleMode = IFX_FALSE; + +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + if (VMMC_SUCCESS(ret)) + { + /* Reduce the number of ALM channels in the capabilities if the SLIC +--- a/src/drv_vmmc_ioctl.c ++++ b/src/drv_vmmc_ioctl.c +@@ -273,7 +273,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP + case FIO_GET_VERS: + { + VMMC_IO_VERSION *pVers; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + VMMC_SDD_REVISION_READ_t *pSDDVersCmd = IFX_NULL; + #endif /*SYSTEM_AR9 || SYSTEM_VR9*/ + SYS_VER_t *pCmd; +@@ -322,7 +322,7 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP + pVers->nTapiVers = 3; + pVers->nDrvVers = MAJORSTEP << 24 | MINORSTEP << 16 | + VERSIONSTEP << 8 | VERS_TYPE; +-#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) ++#if defined(SYSTEM_AR9) || defined(SYSTEM_VR9) || defined(SYSTEM_FALCON) + /* in case of SmartSLIC based systems, we can give some more + versions.*/ + if (VMMC_ALM_SmartSLIC_IsConnected(pDev)) diff --git a/package/system/mmc_over_gpio/Makefile b/package/system/mmc_over_gpio/Makefile new file mode 100644 index 0000000000..03096ad033 --- /dev/null +++ b/package/system/mmc_over_gpio/Makefile @@ -0,0 +1,78 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mmc-over-gpio +PKG_RELEASE:=4 + +include $(INCLUDE_DIR)/package.mk + + +define KernelPackage/mmc-over-gpio + SUBMENU:=Other modules + DEPENDS:=@GPIO_SUPPORT +kmod-mmc-spi +kmod-spi-gpio-old + KCONFIG:=CONFIG_GPIOMMC \ + CONFIG_CONFIGFS_FS=y + TITLE:=MMC/SD card over GPIO support + FILES:=$(LINUX_DIR)/drivers/mmc/host/gpiommc.ko + AUTOLOAD:=$(call AutoLoad,93,gpiommc) + MENU:=1 +endef + +define Package/kmod-mmc-over-gpio/config + menu "Configuration" + depends PACKAGE_kmod-mmc-over-gpio + + config KMOD_MMC_OVER_GPIO_DI_PIN + int "GPIO DI (Data-In) pin" + default 1 + + config KMOD_MMC_OVER_GPIO_DO_PIN + int "GPIO DO (Data-Out) pin" + default 3 + + config KMOD_MMC_OVER_GPIO_CLK_PIN + int "GPIO CLK (Clock) pin" + default 4 + + config KMOD_MMC_OVER_GPIO_CS_PIN + int "GPIO CS (Chip-Select) pin" + default 7 + + endmenu +endef + +define KernelPackage/mmc-over-gpio/description + Support for driving an MMC/SD card over GPIO pins via SPI. +endef + +define KernelPackage/mmc-over-gpio/conffiles +/etc/config/mmc_over_gpio +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) +endef + +define Build/Compile +endef + +define KernelPackage/mmc-over-gpio/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) ./files/mmc_over_gpio.config $(1)/etc/config/mmc_over_gpio + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/mmc_over_gpio.init $(1)/etc/init.d/mmc_over_gpio + + $(SED) 's,@GPIO_DI_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_DI_PIN),g' \ + -e 's,@GPIO_DO_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_DO_PIN),g' \ + -e 's,@GPIO_CLK_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_CLK_PIN),g' \ + -e 's,@GPIO_CS_PIN@,$(CONFIG_KMOD_MMC_OVER_GPIO_CS_PIN),g' \ + $(1)/etc/config/mmc_over_gpio +endef + +$(eval $(call KernelPackage,mmc-over-gpio)) diff --git a/package/system/mmc_over_gpio/files/mmc_over_gpio.config b/package/system/mmc_over_gpio/files/mmc_over_gpio.config new file mode 100644 index 0000000000..23f0084857 --- /dev/null +++ b/package/system/mmc_over_gpio/files/mmc_over_gpio.config @@ -0,0 +1,8 @@ +config 'mmc_over_gpio' + option 'name' 'default' + option 'enabled' '0' + option 'DI_pin' '@GPIO_DI_PIN@' + option 'DO_pin' '@GPIO_DO_PIN@' + option 'CLK_pin' '@GPIO_CLK_PIN@' + option 'CS_pin' '@GPIO_CS_PIN@' + option 'mode' '0' diff --git a/package/system/mmc_over_gpio/files/mmc_over_gpio.init b/package/system/mmc_over_gpio/files/mmc_over_gpio.init new file mode 100644 index 0000000000..121c80398c --- /dev/null +++ b/package/system/mmc_over_gpio/files/mmc_over_gpio.init @@ -0,0 +1,83 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2008 OpenWrt.org +START=90 + +CONFIGFS_DIR="/config/gpiommc" + +# add_device(name, DI_pin, DO_pin, CLK_pin, CS_pin, mode) +add_device() { + local dir="$CONFIGFS_DIR/$1" + + mkdir -p $dir + [ $? -eq 0 ] || return 1 + echo $2 > $dir/gpio_data_in + [ $? -eq 0 ] || return 1 + echo $3 > $dir/gpio_data_out + [ $? -eq 0 ] || return 1 + echo $4 > $dir/gpio_clock + [ $? -eq 0 ] || return 1 + echo $5 > $dir/gpio_chipselect + [ $? -eq 0 ] || return 1 + echo $6 > $dir/spi_mode + [ $? -eq 0 ] || return 1 + # XXX We have more config options available. Use defaults for now. + + echo 1 > $dir/register + [ $? -eq 0 ] || return 1 + + return 0 +} + +# remove_device(name) +remove_device() { + local dir="$CONFIGFS_DIR/$1" + + rmdir $dir +} + +mount_configfs() { + # FIXME: This should probably be done somewhere else. + mount | grep configfs + if [ $? -eq 0 ]; then + # already mounted + return 0 + fi + mkdir -p /config + [ $? -eq 0 ] || return 1 + mount configfs -t configfs /config + [ $? -eq 0 ] || return 1 + + return 0 +} + +start_service() { + local section="$1" + config_get "name" "$section" "name" + config_get "DI_pin" "$section" "DI_pin" + config_get "DO_pin" "$section" "DO_pin" + config_get "CLK_pin" "$section" "CLK_pin" + config_get "CS_pin" "$section" "CS_pin" + config_get "mode" "$section" "mode" + config_get_bool "enabled" "$section" "enabled" '1' + [ "$enabled" -gt 0 ] && add_device "$name" $DI_pin $DO_pin $CLK_pin $CS_pin $mode & +} + +stop_service() { + local section="$1" + config_get "name" "$section" "name" + remove_device "$name" +} + +start() { + # Make sure configfs is mounted + mount_configfs + [ $? -eq 0 ] || return 1 + + config_load "mmc_over_gpio" + config_foreach start_service "mmc_over_gpio" +} + +stop() { + config_load "mmc_over_gpio" + config_foreach stop_service "mmc_over_gpio" +} diff --git a/package/system/om-watchdog/Makefile b/package/system/om-watchdog/Makefile new file mode 100644 index 0000000000..7d517a11eb --- /dev/null +++ b/package/system/om-watchdog/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=om-watchdog +PKG_RELEASE:=1 +PKG_VERSION:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/om-watchdog + SECTION:=base + CATEGORY:=Base system + TITLE:=om watchdog + URL:=http://openwrt.org/ +endef + +define Package/om-watchdog/description + This package contains the hw watchdog script for the OM1P and OM2P device. +endef + +define Build/Prepare +endef + +define Build/Compile +endef + +define Build/Compile +endef + +define Package/om-watchdog/install + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_DIR) $(1)/sbin/ + $(INSTALL_BIN) ./files/om-watchdog.init $(1)/etc/init.d/om-watchdog + $(INSTALL_BIN) ./files/om-watchdog $(1)/sbin/om-watchdog +endef + + +$(eval $(call BuildPackage,om-watchdog)) + diff --git a/package/system/om-watchdog/files/om-watchdog b/package/system/om-watchdog/files/om-watchdog new file mode 100644 index 0000000000..d730c68447 --- /dev/null +++ b/package/system/om-watchdog/files/om-watchdog @@ -0,0 +1,15 @@ +#!/bin/sh + +GPIO=$1 + +trap "" INT HUP + +echo $GPIO > /sys/class/gpio/export +echo out > /sys/class/gpio/gpio${GPIO}/direction + +while true; do + echo 1 > /sys/class/gpio/gpio${GPIO}/value + sleep 1 + echo 0 > /sys/class/gpio/gpio${GPIO}/value + sleep 180 +done diff --git a/package/system/om-watchdog/files/om-watchdog.init b/package/system/om-watchdog/files/om-watchdog.init new file mode 100644 index 0000000000..bb44aa4971 --- /dev/null +++ b/package/system/om-watchdog/files/om-watchdog.init @@ -0,0 +1,27 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (C) 2011 OpenWrt.org +# + +START=11 + +SERVICE_DAEMONIZE=1 + +boot() { + if [ -r /lib/ar71xx.sh ]; then + . /lib/ar71xx.sh + local board=$(ar71xx_board_name) + + case "$board" in + "om2p"|"om2p-hs") + service_start /sbin/om-watchdog 12 + ;; + "om2p-lc") + service_start /sbin/om-watchdog 26 + ;; + esac + else + #we assume it is om1p in this case + service_start /sbin/om-watchdog 3 + fi +} diff --git a/package/system/rotary-gpio-custom/Makefile b/package/system/rotary-gpio-custom/Makefile new file mode 100644 index 0000000000..315ec31f4b --- /dev/null +++ b/package/system/rotary-gpio-custom/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2008-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=rotary-gpio-custom +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/rotary-gpio-custom + SUBMENU:=Other modules + TITLE:=Custom GPIO-based rotary encoder device + DEPENDS:=@GPIO_SUPPORT +kmod-input-gpio-encoder + FILES:=$(PKG_BUILD_DIR)/rotary-gpio-custom.ko + KCONFIG:= +endef + +define KernelPackage/rotary-gpio-custom/description + Kernel module for register a custom rotary-gpio-encoder platform device. +endef + +EXTRA_KCONFIG:= \ + CONFIG_ROTARY_GPIO_CUSTOM=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,rotary-gpio-custom)) diff --git a/package/system/rotary-gpio-custom/src/Kconfig b/package/system/rotary-gpio-custom/src/Kconfig new file mode 100644 index 0000000000..b4d55d5354 --- /dev/null +++ b/package/system/rotary-gpio-custom/src/Kconfig @@ -0,0 +1,9 @@ +config ROTARY_GPIO_CUSTOM + tristate "Custom GPIO-based rotary driver" + depends on GENERIC_GPIO + help + This is a driver to register 1 to 4 custom rotary encoder using + GPIO lines. + + This support is also available as a module. If so, the module + will be called rotary-gpio-custom. diff --git a/package/system/rotary-gpio-custom/src/Makefile b/package/system/rotary-gpio-custom/src/Makefile new file mode 100644 index 0000000000..133672687b --- /dev/null +++ b/package/system/rotary-gpio-custom/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_ROTARY_GPIO_CUSTOM} += rotary-gpio-custom.o diff --git a/package/system/rotary-gpio-custom/src/rotary-gpio-custom.c b/package/system/rotary-gpio-custom/src/rotary-gpio-custom.c new file mode 100644 index 0000000000..8cd8ef12ab --- /dev/null +++ b/package/system/rotary-gpio-custom/src/rotary-gpio-custom.c @@ -0,0 +1,188 @@ +/* + * Custom GPIO-based rotary driver + * + * Copyright (C) 2010 Claudio Mignanti <c.mignanti@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Strongly based on Custom GPIO-based I2C driver by: + * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org> + * + * --------------------------------------------------------------------------- + * + * The behaviour of this driver can be altered by setting some parameters + * from the insmod command line. + * + * The following parameters are adjustable: + * + * bus0 These four arguments can be arrays of + * bus1 1-8 unsigned integers as follows: + * bus2 + * bus3 <id>,<steps>,<axis>,<gpioa>,<gpiob>,<inverted> + * + * + * If this driver is built into the kernel, you can use the following kernel + * command line parameters, with the same values as the corresponding module + * parameters listed above: + * + * rotary-gpio-custom.bus0 + * rotary-gpio-custom.bus1 + * rotary-gpio-custom.bus2 + * rotary-gpio-custom.bus3 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/rotary_encoder.h> + +#define DRV_NAME "rotary-gpio-custom" +#define DRV_DESC "Custom GPIO-based rotary driver" +#define DRV_VERSION "0.1.0" + +#define PFX DRV_NAME ": " + +#define BUS_PARAM_REQUIRED 5 +#define BUS_PARAM_COUNT 6 +#define BUS_COUNT_MAX 4 + +static unsigned int bus0[BUS_PARAM_COUNT] __initdata; +static unsigned int bus1[BUS_PARAM_COUNT] __initdata; +static unsigned int bus2[BUS_PARAM_COUNT] __initdata; +static unsigned int bus3[BUS_PARAM_COUNT] __initdata; + +static unsigned int bus_nump[BUS_COUNT_MAX] __initdata; + +#define BUS_PARM_DESC \ + " config -> id,steps,axis,gpioa,gpiob[,inverted]" + +module_param_array(bus0, uint, &bus_nump[0], 0); +MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC); +module_param_array(bus1, uint, &bus_nump[1], 0); +MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC); +module_param_array(bus2, uint, &bus_nump[2], 0); +MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC); +module_param_array(bus3, uint, &bus_nump[3], 0); +MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC); + +static struct platform_device *devices[BUS_COUNT_MAX]; +static unsigned int nr_devices; + +static void rotary_gpio_custom_cleanup(void) +{ + int i; + + for (i = 0; i < nr_devices; i++) + if (devices[i]) + platform_device_put(devices[i]); +} + +static int __init rotary_gpio_custom_add_one(unsigned int id, unsigned int *params) +{ + struct platform_device *pdev; + struct rotary_encoder_platform_data pdata; + int err; + + if (!bus_nump[id]) + return 0; + + if (bus_nump[id] < BUS_PARAM_REQUIRED) { + printk(KERN_ERR PFX "not enough parameters for bus%d\n", id); + err = -EINVAL; + goto err; + } + + pdev = platform_device_alloc("rotary-gpio", params[0]); + if (!pdev) { + err = -ENOMEM; + goto err; + } + + pdata.steps = params[1]; + pdata.axis = params[2]; + pdata.relative_axis = false; + pdata.rollover = false; + pdata.gpio_a = params[3]; + pdata.gpio_b = params[4]; + + if (params[5] == 1) { + pdata.inverted_a = 1; + pdata.inverted_b = 1; + } else { + pdata.inverted_a = 0; + pdata.inverted_b = 0; + } + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put; + + err = platform_device_add(pdev); + if (err) + goto err_put; + + devices[nr_devices++] = pdev; + return 0; + +err_put: + platform_device_put(pdev); +err: + return err; +} + +static int __init rotary_gpio_custom_probe(void) +{ + int err; + + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); + + err = rotary_gpio_custom_add_one(0, bus0); + if (err) goto err; + + err = rotary_gpio_custom_add_one(1, bus1); + if (err) goto err; + + err = rotary_gpio_custom_add_one(2, bus2); + if (err) goto err; + + err = rotary_gpio_custom_add_one(3, bus3); + if (err) goto err; + + if (!nr_devices) { + printk(KERN_ERR PFX "no bus parameter(s) specified\n"); + err = -ENODEV; + goto err; + } + + return 0; + +err: + rotary_gpio_custom_cleanup(); + return err; +} + +#ifdef MODULE +static int __init rotary_gpio_custom_init(void) +{ + return rotary_gpio_custom_probe(); +} +module_init(rotary_gpio_custom_init); + +static void __exit rotary_gpio_custom_exit(void) +{ + rotary_gpio_custom_cleanup(); +} +module_exit(rotary_gpio_custom_exit); +#else +subsys_initcall(rotary_gpio_custom_probe); +#endif /* MODULE*/ + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org >"); +MODULE_AUTHOR("Claudio Mignanti <c.mignanti@gmail.com>"); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); diff --git a/package/system/rtc-rv5c386a/Makefile b/package/system/rtc-rv5c386a/Makefile new file mode 100644 index 0000000000..e13ead528a --- /dev/null +++ b/package/system/rtc-rv5c386a/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 2006-2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=rtc-rv5c386a +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/rtc-rv5c386a + SUBMENU:=Other modules + DEPENDS:=@TARGET_brcm47xx + TITLE:=Driver for RTC RV5C386A (used in WL-700gE and WL-HDD) + AUTOLOAD:=$(call AutoLoad,70,rtc) + FILES:=$(PKG_BUILD_DIR)/rtc.ko +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(BUILDFLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,rtc-rv5c386a)) diff --git a/package/system/rtc-rv5c386a/src/Makefile b/package/system/rtc-rv5c386a/src/Makefile new file mode 100644 index 0000000000..eeb0430774 --- /dev/null +++ b/package/system/rtc-rv5c386a/src/Makefile @@ -0,0 +1,18 @@ +# $Id$ +# +# Makefile for Real Time Clock driver for WL-HDD +# +# Copyright (C) 2007 Andreas Engel +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version +# 2 of the License, or (at your option) any later version. +# + +obj-m := rtc.o + +ifeq ($(MAKING_MODULES),1) + +-include $(TOPDIR)/Rules.make +endif diff --git a/package/system/rtc-rv5c386a/src/rtc.c b/package/system/rtc-rv5c386a/src/rtc.c new file mode 100644 index 0000000000..7c51bf4bf9 --- /dev/null +++ b/package/system/rtc-rv5c386a/src/rtc.c @@ -0,0 +1,611 @@ +/* + * Real Time Clock driver for WL-HDD + * + * Copyright (C) 2007 Andreas Engel + * + * Hacked together mostly by copying the relevant code parts from: + * drivers/i2c/i2c-bcm5365.c + * drivers/i2c/i2c-algo-bit.c + * drivers/char/rtc.c + * + * Note 1: + * This module uses the standard char device (10,135), while the Asus module + * rtcdrv.o uses (12,0). So, both can coexist which might be handy during + * development (but see the comment in rtc_open()). + * + * Note 2: + * You might need to set the clock once after loading the driver the first + * time because the driver switches the chip into 24h mode if it is running + * in 12h mode. + * + * Usage: + * For compatibility reasons with the original asus driver, the time can be + * read and set via the /dev/rtc device entry. The only accepted data format + * is "YYYY:MM:DD:W:HH:MM:SS\n". See OpenWrt wiki for a script which handles + * this format. + * + * In addition, this driver supports the standard ioctl() calls for setting + * and reading the hardware clock, so the ordinary hwclock utility can also + * be used. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TODO: + * - add a /proc/driver/rtc interface? + * - make the battery failure bit available through the /proc interface? + * + * $Id: rtc.c 7 2007-05-25 19:37:01Z ae $ + */ + +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/miscdevice.h> +#include <linux/ioport.h> +#include <linux/fcntl.h> +#include <linux/mc146818rtc.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/rtc.h> +#include <linux/delay.h> +#include <linux/version.h> +#include <linux/gpio.h> +#include <linux/uaccess.h> + +#include <asm/current.h> +#include <asm/system.h> + +#include <bcm47xx.h> +#include <nvram.h> + +#define RTC_IS_OPEN 0x01 /* Means /dev/rtc is in use. */ + +/* Can be changed via a module parameter. */ +static int rtc_debug = 0; + +static unsigned long rtc_status = 0; /* Bitmapped status byte. */ + +/* These settings are platform dependents. */ +unsigned int sda_index = 0; +unsigned int scl_index = 0; + +#define I2C_READ_MASK 1 +#define I2C_WRITE_MASK 0 + +#define I2C_ACK 1 +#define I2C_NAK 0 + +#define RTC_EPOCH 1900 +#define RTC_I2C_ADDRESS (0x32 << 1) +#define RTC_24HOUR_MODE_MASK 0x20 +#define RTC_PM_MASK 0x20 +#define RTC_VDET_MASK 0x40 +#define RTC_Y2K_MASK 0x80 + +/* + * Delay in microseconds for generating the pulses on the I2C bus. We use + * a rather conservative setting here. See datasheet of the RTC chip. + */ +#define ADAP_DELAY 50 + +/* Avoid spurious compiler warnings. */ +#define UNUSED __attribute__((unused)) + +MODULE_AUTHOR("Andreas Engel"); +MODULE_LICENSE("GPL"); + +/* Test stolen from switch-adm.c. */ +module_param(rtc_debug, int, 0); + +static inline void sdalo(void) +{ + gpio_direction_output(sda_index, 1); + udelay(ADAP_DELAY); +} + +static inline void sdahi(void) +{ + gpio_direction_input(sda_index); + udelay(ADAP_DELAY); +} + +static inline void scllo(void) +{ + gpio_direction_output(scl_index, 1); + udelay(ADAP_DELAY); +} + +static inline int getscl(void) +{ + return (gpio_get_value(scl_index)); +} + +static inline int getsda(void) +{ + return (gpio_get_value(sda_index)); +} + +/* + * We shouldn't simply set the SCL pin to high. Like SDA, the SCL line is + * bidirectional too. According to the I2C spec, the slave is allowed to + * pull down the SCL line to slow down the clock, so we need to check this. + * Generally, we'd need a timeout here, but in our case, we just check the + * line, assuming the RTC chip behaves well. + */ +static int sclhi(void) +{ + gpio_direction_input(scl_index); + udelay(ADAP_DELAY); + if (!getscl()) { + printk(KERN_ERR "SCL pin should be low\n"); + return -ETIMEDOUT; + } + return 0; +} + +static void i2c_start(void) +{ + sdalo(); + scllo(); +} + +static void i2c_stop(void) +{ + sdalo(); + sclhi(); + sdahi(); +} + +static int i2c_outb(int c) +{ + int i; + int ack; + + /* assert: scl is low */ + for (i = 7; i >= 0; i--) { + if (c & ( 1 << i )) { + sdahi(); + } else { + sdalo(); + } + if (sclhi() < 0) { /* timed out */ + sdahi(); /* we don't want to block the net */ + return -ETIMEDOUT; + }; + scllo(); + } + sdahi(); + if (sclhi() < 0) { + return -ETIMEDOUT; + }; + /* read ack: SDA should be pulled down by slave */ + ack = getsda() == 0; /* ack: sda is pulled low ->success. */ + scllo(); + + if (rtc_debug) + printk(KERN_DEBUG "i2c_outb(0x%02x) -> %s\n", + c, ack ? "ACK": "NAK"); + + return ack; /* return 1 if device acked */ + /* assert: scl is low (sda undef) */ +} + +static int i2c_inb(int ack) +{ + int i; + unsigned int indata = 0; + + /* assert: scl is low */ + + sdahi(); + for (i = 0; i < 8; i++) { + if (sclhi() < 0) { + return -ETIMEDOUT; + }; + indata *= 2; + if (getsda()) + indata |= 0x01; + scllo(); + } + if (ack) { + sdalo(); + } else { + sdahi(); + } + + if (sclhi() < 0) { + sdahi(); + return -ETIMEDOUT; + } + scllo(); + sdahi(); + + if (rtc_debug) + printk(KERN_DEBUG "i2c_inb() -> 0x%02x\n", indata); + + /* assert: scl is low */ + return indata & 0xff; +} + +static void i2c_init(void) +{ + /* no gpio_control for EXTIF */ + // ssb_gpio_control(&ssb, sda_mask | scl_mask, 0); + + gpio_set_value(sda_index, 0); + gpio_set_value(scl_index, 0); + sdahi(); + sclhi(); +} + +static int rtc_open(UNUSED struct inode *inode, UNUSED struct file *filp) +{ + spin_lock_irq(&rtc_lock); + + if (rtc_status & RTC_IS_OPEN) { + spin_unlock_irq(&rtc_lock); + return -EBUSY; + } + + rtc_status |= RTC_IS_OPEN; + + /* + * The following call is only necessary if we use both this driver and + * the proprietary one from asus at the same time (which, b.t.w. only + * makes sense during development). Otherwise, each access via the asus + * driver will make access via this driver impossible. + */ + i2c_init(); + + spin_unlock_irq(&rtc_lock); + + return 0; +} + +static int rtc_release(UNUSED struct inode *inode, UNUSED struct file *filp) +{ + /* No need for locking here. */ + rtc_status &= ~RTC_IS_OPEN; + return 0; +} + +static int from_bcd(int bcdnum) +{ + int fac, num = 0; + + for (fac = 1; bcdnum; fac *= 10) { + num += (bcdnum % 16) * fac; + bcdnum /= 16; + } + + return num; +} + +static int to_bcd(int decnum) +{ + int fac, num = 0; + + for (fac = 1; decnum; fac *= 16) { + num += (decnum % 10) * fac; + decnum /= 10; + } + + return num; +} + +static void get_rtc_time(struct rtc_time *rtc_tm) +{ + int cr2; + + /* + * Read date and time from the RTC. We use read method (3). + */ + + spin_lock_irq(&rtc_lock); + i2c_start(); + i2c_outb(RTC_I2C_ADDRESS | I2C_READ_MASK); + cr2 = i2c_inb(I2C_ACK); + rtc_tm->tm_sec = i2c_inb(I2C_ACK); + rtc_tm->tm_min = i2c_inb(I2C_ACK); + rtc_tm->tm_hour = i2c_inb(I2C_ACK); + rtc_tm->tm_wday = i2c_inb(I2C_ACK); + rtc_tm->tm_mday = i2c_inb(I2C_ACK); + rtc_tm->tm_mon = i2c_inb(I2C_ACK); + rtc_tm->tm_year = i2c_inb(I2C_NAK); + i2c_stop(); + spin_unlock_irq(&rtc_lock); + + if (cr2 & RTC_VDET_MASK) { + printk(KERN_WARNING "***RTC BATTERY FAILURE***\n"); + } + + /* Handle century bit */ + if (rtc_tm->tm_mon & RTC_Y2K_MASK) { + rtc_tm->tm_mon &= ~RTC_Y2K_MASK; + rtc_tm->tm_year += 0x100; + } + + rtc_tm->tm_sec = from_bcd(rtc_tm->tm_sec); + rtc_tm->tm_min = from_bcd(rtc_tm->tm_min); + rtc_tm->tm_hour = from_bcd(rtc_tm->tm_hour); + rtc_tm->tm_mday = from_bcd(rtc_tm->tm_mday); + rtc_tm->tm_mon = from_bcd(rtc_tm->tm_mon) - 1; + rtc_tm->tm_year = from_bcd(rtc_tm->tm_year); + + rtc_tm->tm_isdst = -1; /* DST not known */ +} + +static void set_rtc_time(struct rtc_time *rtc_tm) +{ + rtc_tm->tm_sec = to_bcd(rtc_tm->tm_sec); + rtc_tm->tm_min = to_bcd(rtc_tm->tm_min); + rtc_tm->tm_hour = to_bcd(rtc_tm->tm_hour); + rtc_tm->tm_mday = to_bcd(rtc_tm->tm_mday); + rtc_tm->tm_mon = to_bcd(rtc_tm->tm_mon + 1); + rtc_tm->tm_year = to_bcd(rtc_tm->tm_year); + + if (rtc_tm->tm_year >= 0x100) { + rtc_tm->tm_year -= 0x100; + rtc_tm->tm_mon |= RTC_Y2K_MASK; + } + + spin_lock_irq(&rtc_lock); + i2c_start(); + i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK); + i2c_outb(0x00); /* set starting register to 0 (=seconds) */ + i2c_outb(rtc_tm->tm_sec); + i2c_outb(rtc_tm->tm_min); + i2c_outb(rtc_tm->tm_hour); + i2c_outb(rtc_tm->tm_wday); + i2c_outb(rtc_tm->tm_mday); + i2c_outb(rtc_tm->tm_mon); + i2c_outb(rtc_tm->tm_year); + i2c_stop(); + spin_unlock_irq(&rtc_lock); +} + +static ssize_t rtc_write(UNUSED struct file *filp, const char *buf, + size_t count, loff_t *ppos) +{ + struct rtc_time rtc_tm; + char buffer[23]; + char *p; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (ppos != &filp->f_pos) + return -ESPIPE; + + /* + * For simplicity, the only acceptable format is: + * YYYY:MM:DD:W:HH:MM:SS\n + */ + + if (count != 22) + goto err_out; + + if (copy_from_user(buffer, buf, count)) + return -EFAULT; + + buffer[sizeof(buffer)-1] = '\0'; + + p = &buffer[0]; + + rtc_tm.tm_year = simple_strtoul(p, &p, 10); + if (*p++ != ':') goto err_out; + + rtc_tm.tm_mon = simple_strtoul(p, &p, 10) - 1; + if (*p++ != ':') goto err_out; + + rtc_tm.tm_mday = simple_strtoul(p, &p, 10); + if (*p++ != ':') goto err_out; + + rtc_tm.tm_wday = simple_strtoul(p, &p, 10); + if (*p++ != ':') goto err_out; + + rtc_tm.tm_hour = simple_strtoul(p, &p, 10); + if (*p++ != ':') goto err_out; + + rtc_tm.tm_min = simple_strtoul(p, &p, 10); + if (*p++ != ':') goto err_out; + + rtc_tm.tm_sec = simple_strtoul(p, &p, 10); + if (*p != '\n') goto err_out; + + rtc_tm.tm_year -= RTC_EPOCH; + + set_rtc_time(&rtc_tm); + + *ppos += count; + + return count; + + err_out: + printk(KERN_ERR "invalid format: use YYYY:MM:DD:W:HH:MM:SS\\n\n"); + return -EINVAL; +} + + +static ssize_t rtc_read(UNUSED struct file *filp, char *buf, size_t count, + loff_t *ppos) +{ + char wbuf[23]; + struct rtc_time tm; + ssize_t len; + + if (count == 0 || *ppos != 0) + return 0; + + get_rtc_time(&tm); + + len = sprintf(wbuf, "%04d:%02d:%02d:%d:%02d:%02d:%02d\n", + tm.tm_year + RTC_EPOCH, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_wday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); + + if (len > (ssize_t)count) + len = count; + + if (copy_to_user(buf, wbuf, len)) + return -EFAULT; + + *ppos += len; + + return len; +} + +static int rtc_do_ioctl(unsigned int cmd, unsigned long arg) +{ + struct rtc_time rtc_tm; + + switch (cmd) { + case RTC_RD_TIME: + memset(&rtc_tm, 0, sizeof(struct rtc_time)); + get_rtc_time(&rtc_tm); + if (copy_to_user((void *)arg, &rtc_tm, sizeof(rtc_tm))) + return -EFAULT; + break; + + case RTC_SET_TIME: + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&rtc_tm, (struct rtc_time *)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + set_rtc_time(&rtc_tm); + break; + + default: + return -ENOTTY; + } + + return 0; +} + +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + ret = rtc_do_ioctl(cmd, arg); + return ret; +} + +static const struct file_operations rtc_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = rtc_read, + .write = rtc_write, + .unlocked_ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, +}; + +static struct miscdevice rtc_dev = { + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops, +}; + +/* Savagely ripped from diag.c. */ +static inline int startswith (char *source, char *cmp) +{ + return !strncmp(source, cmp, strlen(cmp)); +} + +static void platform_detect(void) +{ + char buf[20]; + int et0phyaddr, et1phyaddr; + + /* Based on "model_no". */ + if (nvram_getenv("model_no", buf, sizeof(buf)) >= 0) { + if (startswith(buf, "WL700")) { /* WL700* */ + sda_index = 2; + scl_index = 5; + return; + } + } + + if (nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ) + et0phyaddr = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ) + et1phyaddr = simple_strtoul(buf, NULL, 0); + + if (nvram_getenv("hardware_version", buf, sizeof(buf)) >= 0) { + /* Either WL-300g or WL-HDD, do more extensive checks */ + if (startswith(buf, "WL300-") && et0phyaddr == 0 && et1phyaddr == 1) { + sda_index = 4; + scl_index = 5; + return; + } + } + /* not found */ +} + +static int __init rtc_init(void) +{ + int cr1; + + platform_detect(); + + if (sda_index == scl_index) { + printk(KERN_ERR "RTC-RV5C386A: unrecognized platform!\n"); + return -ENODEV; + } + + i2c_init(); + + /* + * Switch RTC to 24h mode + */ + spin_lock_irq(&rtc_lock); + i2c_start(); + i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK); + i2c_outb(0xE4); /* start at address 0xE, transmission mode 4 */ + cr1 = i2c_inb(I2C_NAK); + i2c_stop(); + spin_unlock_irq(&rtc_lock); + if ((cr1 & RTC_24HOUR_MODE_MASK) == 0) { + /* RTC is running in 12h mode */ + printk(KERN_INFO "rtc.o: switching to 24h mode\n"); + spin_lock_irq(&rtc_lock); + i2c_start(); + i2c_outb(RTC_I2C_ADDRESS | I2C_WRITE_MASK); + i2c_outb(0xE0); + i2c_outb(cr1 | RTC_24HOUR_MODE_MASK); + i2c_stop(); + spin_unlock_irq(&rtc_lock); + } + + misc_register(&rtc_dev); + + printk(KERN_INFO "RV5C386A Real Time Clock Driver loaded\n"); + + return 0; +} + +static void __exit rtc_exit (void) +{ + misc_deregister(&rtc_dev); + printk(KERN_INFO "Successfully removed RTC RV5C386A driver\n"); +} + +module_init(rtc_init); +module_exit(rtc_exit); + +/* + * Local Variables: + * indent-tabs-mode:t + * c-basic-offset:8 + * End: + */ diff --git a/package/system/sierra-directip/Makefile b/package/system/sierra-directip/Makefile new file mode 100644 index 0000000000..fc0e4ea52c --- /dev/null +++ b/package/system/sierra-directip/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=sierra-directip +PKG_RELEASE:=10 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/usb-sierrawireless-directip + SUBMENU:=USB Support + DEPENDS:=+kmod-usb-serial +kmod-usb-net + TITLE:=Updated Sierra Wireless drivers for DirectIP + FILES:= \ + $(PKG_BUILD_DIR)/sierra.ko \ + $(PKG_BUILD_DIR)/sierra_net.ko + AUTOLOAD:=$(call AutoLoad,60,sierra sierra_net) +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ + $(Build/Patch) +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(BUILDFLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,usb-sierrawireless-directip)) diff --git a/package/system/sierra-directip/patches/100-sierra_net_endian.patch b/package/system/sierra-directip/patches/100-sierra_net_endian.patch new file mode 100644 index 0000000000..196d77d49d --- /dev/null +++ b/package/system/sierra-directip/patches/100-sierra_net_endian.patch @@ -0,0 +1,22 @@ +--- a/sierra_net.c ++++ b/sierra_net.c +@@ -840,8 +840,8 @@ static int sierra_net_bind(struct usbnet + init_timer(&priv->sync_timer); + /* verify fw attributes */ + status = sierra_net_get_fw_attr(dev, &fwattr); +- dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr); +- if (status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_APM)) { ++ dev_dbg(&dev->udev->dev, "Fw attr: %x\n", cpu_to_le16(fwattr)); ++ if (status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_APM)) { + /******************************************************************************* + * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced + * to auto, the following needs to be compiled in. +@@ -856,7 +856,7 @@ static int sierra_net_bind(struct usbnet + usb_disable_autosuspend(dev->udev); + } + /* test whether firmware supports DHCP */ +- if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) { ++ if (!(status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_MASK))) { + /* found incompatible firmware version */ + dev_err(&dev->udev->dev, "Incompatible driver and firmware" + " versions\n"); diff --git a/package/system/sierra-directip/patches/110-drop_dhcp_requirement.patch b/package/system/sierra-directip/patches/110-drop_dhcp_requirement.patch new file mode 100644 index 0000000000..4c4d0ba655 --- /dev/null +++ b/package/system/sierra-directip/patches/110-drop_dhcp_requirement.patch @@ -0,0 +1,14 @@ +--- a/sierra_net.c ++++ b/sierra_net.c +@@ -858,10 +858,7 @@ static int sierra_net_bind(struct usbnet + /* test whether firmware supports DHCP */ + if (!(status == sizeof(fwattr) && (cpu_to_le16(fwattr) & SWI_GET_FW_ATTR_MASK))) { + /* found incompatible firmware version */ +- dev_err(&dev->udev->dev, "Incompatible driver and firmware" +- " versions\n"); +- kfree(priv); +- return -ENODEV; ++ dev_err(&dev->udev->dev, "Warning: Firmware does not have DHCP support\n"); + } + /* prepare sync message from template */ + memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); diff --git a/package/system/sierra-directip/src/Makefile b/package/system/sierra-directip/src/Makefile new file mode 100644 index 0000000000..7ceb03b58c --- /dev/null +++ b/package/system/sierra-directip/src/Makefile @@ -0,0 +1 @@ +obj-m := sierra.o sierra_net.o diff --git a/package/system/sierra-directip/src/sierra.c b/package/system/sierra-directip/src/sierra.c new file mode 100644 index 0000000000..9752d11422 --- /dev/null +++ b/package/system/sierra-directip/src/sierra.c @@ -0,0 +1,1409 @@ +/* + USB Driver for Sierra Wireless + + Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com>, + + Copyright (C) 2008 - 2011 Elina Pasheva, Matthew Safar, Rory Filer + <linux@sierrawireless.com> + + IMPORTANT DISCLAIMER: This driver is not commercially supported by + Sierra Wireless. Use at your own risk. + + This driver is free software; you can redistribute it and/or modify + it under the terms of Version 2 of the GNU General Public License as + published by the Free Software Foundation. + + Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de> + Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> +*/ +/* Uncomment to log function calls */ +/*#define DEBUG*/ +/* Uncomment to force power level set to auto when attaching a device */ +/*#define POWER_LEVEL_AUTO*/ + +/* Sierra driver - kernel 3.0 */ +#define DRIVER_VERSION "v.1.7.40" +#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" +#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" + +#include <linux/kernel.h> +#include <linux/jiffies.h> +#include <linux/errno.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/tty_flip.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> +#include <asm/unaligned.h> + +#define SWIMS_USB_REQUEST_SetPower 0x00 +#define SWIMS_USB_REQUEST_GetFwAttr 0x06 +#define SWIMS_USB_REQUEST_SetNmea 0x07 +#define USB_REQUEST_TYPE_CLASS 0xA1 +#define USB_REQUEST_IFACE 0x20 + +#define N_IN_URB_HM 8 +#define N_OUT_URB_HM 64 +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 + +#define MAX_TRANSFER (PAGE_SIZE - 512) +/* MAX_TRANSFER is chosen so that the VM is not stressed by + allocations > PAGE_SIZE and the number of packets in a page + is an integer 512 is the largest possible packet on EHCI */ + +#define SWI_FW_ATTR_PM_MASK 0x02 +/* PORTION_LEN defines the length of device attribute buffer */ +#define PORTION_LEN 4096 + +static int debug; +static int nmea; + +/* sysfs attributes */ +static int sierra_create_sysfs_attrs(struct usb_serial_port *port); +static int sierra_remove_sysfs_attrs(struct usb_serial_port *port); + +/* Used in interface blacklisting */ +struct sierra_iface_info { + const u32 infolen; /* number of interface numbers on blacklist */ + const u8 *ifaceinfo; /* pointer to the array holding the numbers */ +}; + +/* per interface statistics */ +struct sierra_intf_stats { + atomic_t rx_bytes; /* received bytes */ + atomic_t indat_cb_cnt; /* indat callback count */ + atomic_t indat_cb_fail; /* indat cb with error */ + + atomic_t tx_bytes; /* transmitted bytes */ + atomic_t write_cnt; /* no. of writes */ + atomic_t write_err; /* no. of failed writes */ + + atomic_t delayed_writes; /* no. of delayed writes */ + atomic_t delayed_write_err; /* no. of delayed write errs */ + + atomic_t outdat_cb_cnt; /* outdat callback count */ + atomic_t outdat_cb_fail; /* outdat cb with error */ + +}; + +struct sierra_intf_private { + spinlock_t susp_lock; + unsigned int suspended:1; + int in_flight; + + struct sierra_intf_stats stats; +}; + +static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) +{ + int result; + dev_dbg(&udev->dev, "%s\n", __func__); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + SWIMS_USB_REQUEST_SetPower, /* __u8 request */ + USB_TYPE_VENDOR, /* __u8 request type */ + swiState, /* __u16 value */ + 0, /* __u16 index */ + NULL, /* void *data */ + 0, /* __u16 size */ + USB_CTRL_SET_TIMEOUT); /* int timeout */ + return result; +} + +static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) +{ + int result; + dev_dbg(&udev->dev, "%s\n", __func__); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + SWIMS_USB_REQUEST_SetNmea, /* __u8 request */ + USB_TYPE_VENDOR, /* __u8 request type */ + enable, /* __u16 value */ + 0x0000, /* __u16 index */ + NULL, /* void *data */ + 0, /* __u16 size */ + USB_CTRL_SET_TIMEOUT); /* int timeout */ + return result; +} + +static int sierra_get_fw_attr(struct usb_device *udev, u16 *data) +{ + int result; + u16 *attrdata; + + dev_dbg(&udev->dev, "%s\n", __func__); + + attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL); + if (!attrdata) + return -ENOMEM; + + result = usb_control_msg(udev, + usb_rcvctrlpipe(udev, 0), + SWIMS_USB_REQUEST_GetFwAttr, /* __u8 request*/ + USB_TYPE_VENDOR | USB_DIR_IN, /* request type*/ + 0x0000, /* __u16 value */ + 0x0000, /* __u16 index */ + attrdata, /* void *data */ + sizeof(*attrdata), /* _u16 size */ + USB_CTRL_SET_TIMEOUT); /* in timeout */ + + if (result < 0) { + kfree(attrdata); + return -EIO; + } + + *data = *attrdata; + + kfree(attrdata); + return result; +} + +static int sierra_calc_num_ports(struct usb_serial *serial) +{ + int num_ports = 0; + u8 ifnum, numendpoints; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; + numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints; + + /* Dummy interface present on some SKUs should be ignored */ + if (ifnum == 0x99) + num_ports = 0; + else if (numendpoints <= 3) + num_ports = 1; + else + num_ports = (numendpoints-1)/2; + return num_ports; +} + +static int is_blacklisted(const u8 ifnum, + const struct sierra_iface_info *blacklist) +{ + const u8 *info; + int i; + + if (blacklist) { + info = blacklist->ifaceinfo; + + for (i = 0; i < blacklist->infolen; i++) { + if (info[i] == ifnum) + return 1; + } + } + return 0; +} + +static int is_himemory(const u8 ifnum, + const struct sierra_iface_info *himemorylist) +{ + const u8 *info; + int i; + + if (himemorylist) { + info = himemorylist->ifaceinfo; + + for (i=0; i < himemorylist->infolen; i++) { + if (info[i] == ifnum) + return 1; + } + } + return 0; +} + +static int sierra_calc_interface(struct usb_serial *serial) +{ + int interface; + struct usb_interface *p_interface; + struct usb_host_interface *p_host_interface; + + /* Get the interface structure pointer from the serial struct */ + p_interface = serial->interface; + + /* Get a pointer to the host interface structure */ + p_host_interface = p_interface->cur_altsetting; + + /* read the interface descriptor for this active altsetting + * to find out the interface number we are on */ + interface = p_host_interface->desc.bInterfaceNumber; + + return interface; +} + +static int sierra_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + int result = 0; + struct usb_device *udev; + struct sierra_intf_private *intfdata; + u8 ifnum; + + udev = serial->dev; + dev_dbg(&udev->dev, "%s\n", __func__); + + ifnum = sierra_calc_interface(serial); + /* + * If this interface supports more than 1 alternate + * select the 2nd one + */ + if (serial->interface->num_altsetting == 2) { + dev_dbg(&udev->dev, "Selecting alt setting for interface %d\n", + ifnum); + /* We know the alternate setting is for composite USB interface + * modems + */ + usb_set_interface(udev, ifnum, 1); + } + + /* ifnum could have changed - by calling usb_set_interface */ + ifnum = sierra_calc_interface(serial); + + if (is_blacklisted(ifnum, + (struct sierra_iface_info *)id->driver_info)) { + dev_dbg(&serial->dev->dev, + "Ignoring blacklisted interface #%d\n", ifnum); + return -ENODEV; + } + + intfdata = serial->private = kzalloc(sizeof(struct sierra_intf_private), + GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + spin_lock_init(&intfdata->susp_lock); + + return result; +} + +/* interfaces with higher memory requirements */ +static const u8 hi_memory_typeA_ifaces[] = { 0, 2 }; +static const struct sierra_iface_info typeA_interface_list = { + .infolen = ARRAY_SIZE(hi_memory_typeA_ifaces), + .ifaceinfo = hi_memory_typeA_ifaces, +}; + +static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 }; +static const struct sierra_iface_info typeB_interface_list = { + .infolen = ARRAY_SIZE(hi_memory_typeB_ifaces), + .ifaceinfo = hi_memory_typeB_ifaces, +}; + +/* 'blacklist' of interfaces not served by this driver */ +static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; +static const struct sierra_iface_info direct_ip_interface_blacklist = { + .infolen = ARRAY_SIZE( direct_ip_non_serial_ifaces ), + .ifaceinfo = direct_ip_non_serial_ifaces, +}; + +static const struct usb_device_id id_table [] = { + { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ + { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */ + { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */ + { USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */ + + { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ + { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */ + { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ + { USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */ + { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ + { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ + { USB_DEVICE(0x1199, 0x0301) }, /* Sierra Wireless USB Dongle 250U/3G */ + /* Sierra Wireless MC5728 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0400, 0xFF, 0xFF, 0xFF) }, + + /* Sierra Wireless C597 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, + /* Sierra Wireless T598 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, + { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */ + { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */ + { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */ + { USB_DEVICE(0x114F, 0x6000) }, /* Sierra Wireless Q26 Elite */ + + { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ + { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ + { USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */ + { USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ + { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ + { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ + { USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */ + { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ + { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ + { USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */ + { USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */ + { USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */ + { USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */ + { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ + { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ + /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ + { USB_DEVICE(0x1199, 0x683C) }, + { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8791 Composite */ + /* Sierra Wireless MC8790, MC8791, MC8792 */ + { USB_DEVICE(0x1199, 0x683E) }, + { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ + { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ + { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ + { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */ + { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */ + { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ + { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */ + { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ + /* Sierra Wireless C885 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, + /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, + /* Sierra Wireless C22/C33 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)}, + /* Sierra Wireless HSPA Non-Composite Device */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, + { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ + /* Sierra Wireless Direct IP modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + /* AT&T Direct IP modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + /* Sierra Wireless Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + /* Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */ + { USB_DEVICE(0x413C, 0x8133) }, + + { } +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* per port private data */ +struct sierra_port_private { + spinlock_t lock; /* lock the structure */ + int outstanding_urbs; /* number of out urbs in flight */ + + struct usb_anchor active; + struct usb_anchor delayed; + + int num_out_urbs; + int num_in_urbs; + /* Input endpoints and buffers for this port */ + struct urb *in_urbs[N_IN_URB_HM]; + + /* Settings for the port */ + int rts_state; /* Handshaking pins (outputs) */ + int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; + unsigned int opened:1; +}; + +static int sierra_send_setup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + __u16 interface = 0; + int val = 0; + int do_send = 0; + int retval; + + dev_dbg(&port->dev, "%s\n", __func__); + + if (portdata->dtr_state) + val |= 0x01; + if (portdata->rts_state) + val |= 0x02; + + /* If composite device then properly report interface */ + if (serial->num_ports == 1) { + interface = sierra_calc_interface(serial); + /* Control message is sent only to interfaces with + * interrupt_in endpoints + */ + if (port->interrupt_in_urb) { + /* send control message */ + do_send = 1; + } + } + + /* Otherwise the need to do non-composite mapping */ + else { + if (port->bulk_out_endpointAddress == 2) + interface = 0; + else if (port->bulk_out_endpointAddress == 4) + interface = 1; + else if (port->bulk_out_endpointAddress == 5) + interface = 2; + + do_send = 1; + } + if (!do_send) + return 0; + + usb_autopm_get_interface(serial->interface); + retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); + usb_autopm_put_interface(serial->interface); + + return retval; +} + +static void sierra_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + dev_dbg(&port->dev, "%s\n", __func__); + tty_termios_copy_hw(tty->termios, old_termios); + sierra_send_setup(port); +} + +static int sierra_tiocmget(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int value; + struct sierra_port_private *portdata; + + dev_dbg(&port->dev, "%s\n", __func__); + portdata = usb_get_serial_port_data(port); + + value = ((portdata->rts_state) ? TIOCM_RTS : 0) | + ((portdata->dtr_state) ? TIOCM_DTR : 0) | + ((portdata->cts_state) ? TIOCM_CTS : 0) | + ((portdata->dsr_state) ? TIOCM_DSR : 0) | + ((portdata->dcd_state) ? TIOCM_CAR : 0) | + ((portdata->ri_state) ? TIOCM_RNG : 0); + + return value; +} + +static int sierra_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + + if (set & TIOCM_RTS) + portdata->rts_state = 1; + if (set & TIOCM_DTR) + portdata->dtr_state = 1; + + if (clear & TIOCM_RTS) + portdata->rts_state = 0; + if (clear & TIOCM_DTR) + portdata->dtr_state = 0; + return sierra_send_setup(port); +} + +static void sierra_release_urb(struct urb *urb) +{ + struct usb_serial_port *port; + if (urb) { + port = urb->context; + dev_dbg(&port->dev, "%s: %p\n", __func__, urb); + usb_free_urb(urb); + } +} + +/* Sysfs Attributes */ + +static ssize_t show_suspend_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_serial_port *port; + struct sierra_port_private *portdata; + struct sierra_intf_private *intfdata; + unsigned long flags; + unsigned int flag_suspended = 0; + + port = to_usb_serial_port(dev); + portdata = usb_get_serial_port_data(port); + intfdata = port->serial->private; + + spin_lock_irqsave(&intfdata->susp_lock, flags); + flag_suspended = intfdata->suspended; + spin_unlock_irqrestore(&intfdata->susp_lock, flags); + + return snprintf(buf, PORTION_LEN, "%i\n", flag_suspended); +} + +static ssize_t show_stats(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_serial_port *port; + struct sierra_intf_private *intfdata; + + port = to_usb_serial_port(dev); + intfdata = port->serial->private; + + return snprintf(buf, PORTION_LEN, + "rx: %i B\tindat: %i\tindat err: %i\n" + "tx: %i B\toutdat: %i\toutdat err: %i\n" + "writes: %i\t\twrite err: %i\n" + "delayed writes: %i\tdelayed write err: %i\n", + atomic_read(&intfdata->stats.rx_bytes), atomic_read(&intfdata->stats.indat_cb_cnt), atomic_read(&intfdata->stats.indat_cb_fail), + atomic_read(&intfdata->stats.tx_bytes), atomic_read(&intfdata->stats.outdat_cb_cnt), atomic_read(&intfdata->stats.outdat_cb_fail), + atomic_read(&intfdata->stats.write_cnt), atomic_read(&intfdata->stats.write_err), + atomic_read(&intfdata->stats.delayed_writes), atomic_read(&intfdata->stats.delayed_write_err) + ); +} + +/* Read only suspend status */ +static DEVICE_ATTR(suspend_status, S_IWUSR | S_IRUGO, show_suspend_status, + NULL); + +/* Read only statistics */ +static DEVICE_ATTR(stats, S_IWUSR | S_IRUGO, show_stats, NULL); + +static int sierra_create_sysfs_attrs(struct usb_serial_port *port) +{ + int result = 0; + + result = device_create_file(&port->dev, &dev_attr_stats); + if (unlikely (result < 0)) + return result; + return device_create_file(&port->dev, &dev_attr_suspend_status); +} + +static int sierra_remove_sysfs_attrs(struct usb_serial_port *port) +{ + device_remove_file(&port->dev, &dev_attr_stats); + device_remove_file(&port->dev, &dev_attr_suspend_status); + return 0; +} + +static void sierra_outdat_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct sierra_intf_private *intfdata; + int status = urb->status; + + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); + intfdata = port->serial->private; + + usb_autopm_put_interface_async(port->serial->interface); + + atomic_inc(&intfdata->stats.outdat_cb_cnt); + + if (status) { + dev_dbg(&port->dev, "%s - nonzero write bulk status " + "received: %d\n", __func__, status); + atomic_inc(&intfdata->stats.outdat_cb_fail); + } + + spin_lock(&portdata->lock); + --portdata->outstanding_urbs; + spin_unlock(&portdata->lock); + + spin_lock(&intfdata->susp_lock); + --intfdata->in_flight; + spin_unlock(&intfdata->susp_lock); + + usb_serial_port_softint(port); +} + +/* Write */ +static int sierra_write(struct tty_struct *tty, + struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct sierra_intf_private *intfdata; + struct usb_serial *serial = port->serial; + unsigned long flags; + unsigned char *buffer; + struct urb *urb; + size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER); + int retval = 0; + + /* verify that we actually have some data to write */ + if (count == 0) + return 0; + + dev_dbg(&port->dev, "%s: write (%zu bytes)\n", __func__, writesize); + + intfdata = serial->private; + + spin_lock_irqsave(&portdata->lock, flags); + if (portdata->outstanding_urbs > portdata->num_out_urbs) { + spin_unlock_irqrestore(&portdata->lock, flags); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); + return 0; + } + portdata->outstanding_urbs++; + spin_unlock_irqrestore(&portdata->lock, flags); + + retval = usb_autopm_get_interface_async(serial->interface); + if (unlikely(retval < 0)) { + spin_lock_irqsave(&portdata->lock, flags); + portdata->outstanding_urbs--; + spin_unlock_irqrestore(&portdata->lock, flags); + return retval; + } + + buffer = kmalloc(writesize, GFP_ATOMIC); + if (!buffer) { + dev_err(&port->dev, "out of memory\n"); + spin_lock_irqsave(&portdata->lock, flags); + --portdata->outstanding_urbs; + spin_unlock_irqrestore(&portdata->lock, flags); + usb_autopm_put_interface_async(serial->interface); + return -ENOMEM; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); + kfree(buffer); + spin_lock_irqsave(&portdata->lock, flags); + --portdata->outstanding_urbs; + spin_unlock_irqrestore(&portdata->lock, flags); + usb_autopm_put_interface_async(serial->interface); + return -ENOMEM; + } + + memcpy(buffer, buf, writesize); + + usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer); + + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, writesize, sierra_outdat_callback, port); + + /* Handle the need to send a zero length packet and release the + * transfer buffer + */ + urb->transfer_flags |= (URB_ZERO_PACKET | URB_FREE_BUFFER); + + spin_lock_irqsave(&intfdata->susp_lock, flags); + + if (intfdata->suspended) { + usb_anchor_urb(urb, &portdata->delayed); + spin_unlock_irqrestore(&intfdata->susp_lock, flags); + /* release our reference to this urb, the USB core will + * eventually free it entirely */ + usb_free_urb(urb); + return writesize; + } + usb_anchor_urb(urb, &portdata->active); + + /* send it down the pipe */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + usb_unanchor_urb(urb); + spin_unlock_irqrestore(&intfdata->susp_lock, flags); + + dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " + "with status = %d\n", __func__, retval); + usb_free_urb(urb); + spin_lock_irqsave(&portdata->lock, flags); + --portdata->outstanding_urbs; + spin_unlock_irqrestore(&portdata->lock, flags); + usb_autopm_put_interface_async(serial->interface); + atomic_inc(&intfdata->stats.write_err); + return retval; + } else { + intfdata->in_flight++; + spin_unlock_irqrestore(&intfdata->susp_lock, flags); + atomic_inc(&intfdata->stats.write_cnt); + atomic_add(writesize, &intfdata->stats.tx_bytes); + } + /* release our reference to this urb, the USB core will eventually + * free it entirely */ + usb_free_urb(urb); + + return writesize; +} + +static void sierra_indat_callback(struct urb *urb) +{ + int err; + int endpoint; + struct usb_serial_port *port = urb->context; + struct tty_struct *tty; + struct sierra_intf_private *intfdata; + unsigned char *data = urb->transfer_buffer; + int status = urb->status; + + endpoint = usb_pipeendpoint(urb->pipe); + + dev_dbg(&port->dev, "%s: %p\n", __func__, urb); + + intfdata = port->serial->private; + + atomic_inc(&intfdata->stats.indat_cb_cnt); /* indat calls */ + + if (status) { + dev_dbg(&port->dev, "%s: nonzero status: %d on" + " endpoint %02x\n", __func__, status, endpoint); + atomic_inc(&intfdata->stats.indat_cb_fail); /* indat fails */ + } else { + if (urb->actual_length) { + tty = tty_port_tty_get(&port->port); + if (tty) { + tty_insert_flip_string(tty, data, + urb->actual_length); + tty_flip_buffer_push(tty); + + tty_kref_put(tty); + /* tty invalid after this point */ + /* rx'd bytes */ + atomic_add(urb->actual_length, + &intfdata->stats.rx_bytes); + usb_serial_debug_data(debug, &port->dev, + __func__, urb->actual_length, data); + } + } else { + dev_dbg(&port->dev, "%s: empty read urb" + " received\n", __func__); + } + } + + /* Resubmit urb so we continue receiving */ + if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) { + usb_mark_last_busy(port->serial->dev); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err && err != -ENODEV) + dev_err(&port->dev, "resubmit read urb failed." + "(%d)\n", err); + } + + return; +} + +static void sierra_instat_callback(struct urb *urb) +{ + int err; + int status = urb->status; + struct usb_serial_port *port = urb->context; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct usb_serial *serial = port->serial; + + dev_dbg(&port->dev, "%s: %p\n", __func__, urb); + + if (status == 0) { + struct usb_ctrlrequest *req_pkt = + (struct usb_ctrlrequest *)urb->transfer_buffer; + + const u16 *sigp = (u16 *)(req_pkt + 1); + /* usb_ctrlrequest we parsed is followed by two bytes of data + * make sure we received that many bytes + */ + if (urb->actual_length >= sizeof(*req_pkt) + sizeof(*sigp) && + req_pkt->bRequestType == USB_REQUEST_TYPE_CLASS && + req_pkt->bRequest == USB_REQUEST_IFACE) { + int old_dcd_state; + const u16 signals = get_unaligned_le16(sigp); + struct tty_struct *tty; + + dev_dbg(&port->dev, "%s: signal 0x%x\n", __func__, + signals); + + old_dcd_state = portdata->dcd_state; + /* Note: CTS from modem is in reverse logic! */ + portdata->cts_state = ((signals & 0x100) ? 0 : 1); + portdata->dcd_state = ((signals & 0x01) ? 1 : 0); + portdata->dsr_state = ((signals & 0x02) ? 1 : 0); + portdata->ri_state = ((signals & 0x08) ? 1 : 0); + + tty = tty_port_tty_get(&port->port); + if (tty && !C_CLOCAL(tty) && + old_dcd_state && !portdata->dcd_state) + tty_hangup(tty); + tty_kref_put(tty); + } else { + /* dump the data we don't understand to log */ + usb_serial_debug_data(1, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + } + } else + dev_dbg(&port->dev, "%s: error %d\n", __func__, status); + + /* Resubmit urb so we continue receiving IRQ data */ + if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) { + usb_mark_last_busy(serial->dev); + urb->dev = serial->dev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err && err != -ENODEV) + dev_err(&port->dev, "%s: resubmit intr urb " + "failed. (%d)\n", __func__, err); + } +} + +static int sierra_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + unsigned long flags; + int retval; + + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); + + /* try to give a good number back based on if we have any free urbs at + * this point in time */ + retval = MAX_TRANSFER; + + spin_lock_irqsave(&portdata->lock, flags); + if (portdata->outstanding_urbs >= portdata->num_out_urbs) { + retval = 0; + } + spin_unlock_irqrestore(&portdata->lock, flags); + + return retval; +} + +static void sierra_stop_rx_urbs(struct usb_serial_port *port) +{ + int i; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + + for (i = 0; i < portdata->num_in_urbs; i++) + usb_kill_urb(portdata->in_urbs[i]); + + usb_kill_urb(port->interrupt_in_urb); +} + +static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags) +{ + int ok_cnt; + int err = -EINVAL; + int i; + struct urb *urb; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + + ok_cnt = 0; + for (i = 0; i < portdata->num_in_urbs; i++) { + urb = portdata->in_urbs[i]; + if (!urb) + continue; + urb->transfer_flags |= URB_FREE_BUFFER; + err = usb_submit_urb(urb, mem_flags); + if (err) { + dev_err(&port->dev, "%s: submit urb failed: %d\n", + __func__, err); + } else { + ok_cnt++; + } + } + + if (ok_cnt && port->interrupt_in_urb) { + err = usb_submit_urb(port->interrupt_in_urb, mem_flags); + if (err) { + dev_err(&port->dev, "%s: submit intr urb failed: %d\n", + __func__, err); + } + } + + if (ok_cnt > 0) /* at least one rx urb submitted */ + return 0; + else + return err; +} + +static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, + int dir, void *ctx, int len, + gfp_t mem_flags, + usb_complete_t callback) +{ + struct urb *urb; + u8 *buf; + + if (endpoint == -1) + return NULL; + + urb = usb_alloc_urb(0, mem_flags); + if (urb == NULL) { + dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n", + __func__, endpoint); + return NULL; + } + + buf = kmalloc(len, mem_flags); + if (buf) { + /* Fill URB using supplied data */ + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, endpoint) | dir, + buf, len, callback, ctx); + + /* debug */ + dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__, + dir == USB_DIR_IN ? 'i' : 'o', urb, buf); + } else { + dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__, + dir == USB_DIR_IN ? 'i' : 'o', urb, buf); + + sierra_release_urb(urb); + urb = NULL; + } + + return urb; +} +static void sierra_close(struct usb_serial_port *port) +{ + int i; + struct urb *urb; + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + struct sierra_intf_private *intfdata = port->serial->private; + + dev_dbg(&port->dev, "%s\n", __func__); + portdata = usb_get_serial_port_data(port); + + portdata->rts_state = 0; + portdata->dtr_state = 0; + + usb_autopm_get_interface(serial->interface); + + if (serial->dev) { + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + sierra_send_setup(port); + mutex_unlock(&serial->disc_mutex); + spin_lock_irq(&intfdata->susp_lock); + portdata->opened = 0; + spin_unlock_irq(&intfdata->susp_lock); + + /* Stop reading urbs */ + sierra_stop_rx_urbs(port); + /* .. and release them */ + for (i = 0; i < portdata->num_in_urbs; i++) { + sierra_release_urb(portdata->in_urbs[i]); + portdata->in_urbs[i] = NULL; + } + while((urb = usb_get_from_anchor(&portdata->delayed))) { + sierra_release_urb(urb); + usb_autopm_put_interface(serial->interface); + } + /* wait for active to finish */ + usb_wait_anchor_empty_timeout(&portdata->active, 500); + usb_kill_anchored_urbs(&portdata->active); + + } +} + +static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) +{ + struct sierra_port_private *portdata; + struct usb_serial *serial = port->serial; + struct sierra_intf_private *intfdata = serial->private; + int i; + int err; + int endpoint; + struct urb *urb; + + portdata = usb_get_serial_port_data(port); + + dev_dbg(&port->dev, "%s\n", __func__); + + /* Set some sane defaults */ + portdata->rts_state = 1; + portdata->dtr_state = 1; + + + endpoint = port->bulk_in_endpointAddress; + for (i = 0; i < portdata->num_in_urbs; i++) { + urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, + IN_BUFLEN, GFP_KERNEL, + sierra_indat_callback); + portdata->in_urbs[i] = urb; + } + /* clear halt condition */ + usb_clear_halt(serial->dev, + usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN); + + /* reset outstanding out urbs counter */ + spin_lock_irq(&portdata->lock); + portdata->outstanding_urbs = 0; + spin_unlock_irq(&portdata->lock); + + err = sierra_submit_rx_urbs(port, GFP_KERNEL); + if (err) { + /* do everything as in close() but do not call close() because + * usbserial calls sierra_open() with mutex taken; + * then if we call sierra_close() inside sierra_open() we + * violate 'no nested mutexes' kernel condition + */ + portdata->rts_state = 0; + portdata->dtr_state = 0; + usb_autopm_get_interface(serial->interface); + /* Stop reading urbs */ + sierra_stop_rx_urbs(port); + /* .. and release them */ + for (i = 0; i < portdata->num_in_urbs; i++) { + sierra_release_urb(portdata->in_urbs[i]); + portdata->in_urbs[i] = NULL; + } + while((urb = usb_get_from_anchor(&portdata->delayed))) { + sierra_release_urb(urb); + usb_autopm_put_interface(serial->interface); + } + /* wait for active to finish */ + usb_wait_anchor_empty_timeout(&portdata->active, 500); + usb_kill_anchored_urbs(&portdata->active); + /* restore balance for autopm */ + usb_autopm_put_interface(serial->interface); + return err; + } + sierra_send_setup(port); + + spin_lock_irq(&intfdata->susp_lock); + portdata->opened = 1; + spin_unlock_irq(&intfdata->susp_lock); + usb_autopm_put_interface(serial->interface); + + return 0; +} + +static void sierra_dtr_rts(struct usb_serial_port *port, int on) +{ + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + portdata->rts_state = on; + portdata->dtr_state = on; + + if (serial->dev) { + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) + sierra_send_setup(port); + mutex_unlock(&serial->disc_mutex); + } +} + +static int sierra_startup(struct usb_serial *serial) +{ + struct usb_serial_port *port = NULL; + struct sierra_port_private *portdata = NULL; + struct sierra_iface_info *himemoryp = NULL; + int i; + u8 ifnum; + u16 fw_attr; + int result; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + /* Set Device mode to D0 */ + sierra_set_power_state(serial->dev, 0x0000); + + /* Check NMEA and set */ + if (nmea) + sierra_vsc_set_nmea(serial->dev, 1); + + if (serial->num_ports) { + /* Note: One big piece of memory is allocated for all ports + * private data in one shot. This memory is split into equal + * pieces for each port. + */ + portdata = (struct sierra_port_private *)kzalloc + (sizeof(*portdata) * serial->num_ports, GFP_KERNEL); + if (!portdata) { + dev_dbg(&serial->dev->dev, "%s: No memory!\n", __func__); + return -ENOMEM; + } + } + + /* Now setup per port private data */ + for (i = 0; i < serial->num_ports; i++, portdata++) { + port = serial->port[i]; + /* Initialize selected members of private data because these + * may be referred to right away */ + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + portdata->cts_state = 1; + + ifnum = i; + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = + (struct sierra_iface_info *)&typeB_interface_list; + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + } + else { + himemoryp = + (struct sierra_iface_info *)&typeA_interface_list; + if (is_himemory(i, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + } + dev_dbg(&serial->dev->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); + /* Set the port private data pointer */ + usb_set_serial_port_data(port, portdata); + } + serial->interface->needs_remote_wakeup = 1; + + result = sierra_get_fw_attr(serial->dev, &fw_attr); + if (result == sizeof(fw_attr) && (fw_attr & SWI_FW_ATTR_PM_MASK) ) { + dev_info(&serial->dev->dev, + "APM supported, enabling autosuspend.\n"); +/******************************************************************************* + * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced + * to auto, the following needs to be compiled in. + */ +#ifdef POWER_LEVEL_AUTO + /* make power level default be 'auto' */ + usb_enable_autosuspend(serial->dev); +#endif + } else { + usb_disable_autosuspend(serial->dev); + } + + return 0; +} + +static void sierra_release(struct usb_serial *serial) +{ + int i; + struct usb_serial_port *port; + struct sierra_intf_private *intfdata = serial->private; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + if (serial->num_ports > 0) { + port = serial->port[0]; + if (port) + /* Note: The entire piece of memory that was allocated + * in the startup routine can be released by passing + * a pointer to the beginning of the piece. + * This address corresponds to the address of the chunk + * that was given to port 0. + */ + kfree(usb_get_serial_port_data(port)); + } + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (!port) + continue; + usb_set_serial_port_data(port, NULL); + } + kfree(intfdata); +} + +#ifdef CONFIG_PM +static void stop_read_write_urbs(struct usb_serial *serial) +{ + int i; + struct usb_serial_port *port; + struct sierra_port_private *portdata; + + /* Stop reading/writing urbs */ + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + sierra_stop_rx_urbs(port); + usb_kill_anchored_urbs(&portdata->active); + } +} + +static int sierra_suspend(struct usb_serial *serial, pm_message_t message) +{ + struct sierra_intf_private *intfdata; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + intfdata = serial->private; + spin_lock_irq(&intfdata->susp_lock); + + if (message.event & PM_EVENT_AUTO) { + if (intfdata->in_flight) { + spin_unlock_irq(&intfdata->susp_lock); + return -EBUSY; + } + } + intfdata->suspended = 1; + spin_unlock_irq(&intfdata->susp_lock); + + stop_read_write_urbs(serial); + + return 0; +} + +static int sierra_resume(struct usb_serial *serial) +{ + struct usb_serial_port *port; + struct sierra_intf_private *intfdata = serial->private; + struct sierra_port_private *portdata; + struct urb *urb; + int ec = 0; + int i, err; + int len; + int failed_submits; + + dev_dbg(&serial->dev->dev, "%s\n", __func__); + + spin_lock_irq(&intfdata->susp_lock); + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + failed_submits = 0; + while ((urb = usb_get_from_anchor(&portdata->delayed))) { + usb_anchor_urb(urb, &portdata->active); + intfdata->in_flight++; + len = urb->transfer_buffer_length; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { + intfdata->in_flight--; + usb_unanchor_urb(urb); + failed_submits++; + atomic_inc(&intfdata->stats.delayed_write_err); + /* fix pm_usage_cnt */ + usb_autopm_put_interface_async( + port->serial->interface); + } else { + atomic_inc(&intfdata->stats.delayed_writes); + atomic_add(len, &intfdata->stats.tx_bytes); + } + /* release urb - usb_get_from_anchor increased kref */ + usb_free_urb(urb); + } + + if (portdata->opened) { + err = sierra_submit_rx_urbs(port, GFP_ATOMIC); + if (err) + ec++; + } + if (failed_submits) { + /* fix outstanding_urbs counter */ + spin_lock(&portdata->lock); /* assuming irq disabled */ + portdata->outstanding_urbs -= failed_submits; + spin_unlock(&portdata->lock); + /* unblock a writer */ + usb_serial_port_softint(port); + } + } + intfdata->suspended = 0; + spin_unlock_irq(&intfdata->susp_lock); + + return ec ? -EIO : 0; +} +#else +#define sierra_suspend NULL +#define sierra_resume NULL +#endif + +static int sierra_reset_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + dev_err(&serial->dev->dev, "%s\n", __func__); + return usb_serial_resume(intf); +} + +static struct usb_driver sierra_driver = { + .name = "sierra", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .reset_resume = sierra_reset_resume, + .id_table = id_table, + + .no_dynamic_id = 1, + .supports_autosuspend = 1, +}; + + +static struct usb_serial_driver sierra_device = { + .driver = { + .owner = THIS_MODULE, + .name = "sierra", + }, + .description = "Sierra USB modem", + .id_table = id_table, + .usb_driver = &sierra_driver, + .calc_num_ports = sierra_calc_num_ports, + .probe = sierra_probe, + .open = sierra_open, + .close = sierra_close, + .dtr_rts = sierra_dtr_rts, + .write = sierra_write, + .write_room = sierra_write_room, + .set_termios = sierra_set_termios, + .tiocmget = sierra_tiocmget, + .tiocmset = sierra_tiocmset, + .attach = sierra_startup, + .release = sierra_release, + .port_probe = sierra_create_sysfs_attrs, + .port_remove = sierra_remove_sysfs_attrs, + .suspend = sierra_suspend, + .resume = sierra_resume, + .read_int_callback = sierra_instat_callback, + +}; + +/* Functions used by new usb-serial code. */ +static int __init sierra_init(void) +{ + int retval; + retval = usb_serial_register(&sierra_device); + if (retval) + goto failed_device_register; + + retval = usb_register(&sierra_driver); + if (retval) + goto failed_driver_register; + + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + + return 0; + +failed_driver_register: + usb_serial_deregister(&sierra_device); +failed_device_register: + return retval; +} + +static void __exit sierra_exit(void) +{ + usb_deregister(&sierra_driver); + usb_serial_deregister(&sierra_device); +} + +module_init(sierra_init); +module_exit(sierra_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +module_param(nmea, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(nmea, "NMEA streaming"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages"); diff --git a/package/system/sierra-directip/src/sierra_net.c b/package/system/sierra-directip/src/sierra_net.c new file mode 100644 index 0000000000..f6057d9188 --- /dev/null +++ b/package/system/sierra-directip/src/sierra_net.c @@ -0,0 +1,1123 @@ +/* + * USB-to-WWAN Driver for Sierra Wireless modems + * + * Copyright (C) 2008 - 2011 Paxton Smith, Matthew Safar, Rory Filer + * <linux@sierrawireless.com> + * + * Portions of this based on the cdc_ether driver by David Brownell (2003-2005) + * and Ole Andre Vadla Ravnas (ActiveSync) (2006). + * + * IMPORTANT DISCLAIMER: This driver is not commercially supported by + * Sierra Wireless. Use at your own risk. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DRIVER_VERSION "v.3.2" +#define DRIVER_AUTHOR "Paxton Smith, Matthew Safar, Rory Filer" +#define DRIVER_DESC "USB-to-WWAN Driver for Sierra Wireless modems" +static const char driver_name[] = "sierra_net"; + +/* if defined debug messages enabled */ +/*#define DEBUG*/ +/* more debug messages */ +/*#define VERBOSE*/ +/* Uncomment to force power level set to auto when attaching a device */ +/*#define POWER_LEVEL_AUTO*/ + +#include <linux/module.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <linux/usb.h> +#include <linux/usb/cdc.h> +#include <net/ip.h> +#include <net/udp.h> +#include <asm/unaligned.h> +#include <linux/usb/usbnet.h> + +#define SWI_USB_REQUEST_GET_FW_ATTR 0x06 +#define SWI_GET_FW_ATTR_MASK 0x08 +#define SWI_GET_FW_ATTR_APM 0x2 + +/* atomic counter partially included in MAC address to make sure 2 devices + * do not end up with the same MAC - concept breaks in case of > 255 ifaces + */ +static atomic_t iface_counter = ATOMIC_INIT(0); + +/* + * SYNC Timer Delay definition used to set the expiry time + */ +#define SIERRA_NET_SYNCDELAY (2*HZ) + +/* Max. MTU supported. The modem buffers are limited to 1500 */ +#define SIERRA_NET_MAX_SUPPORTED_MTU 1500 + +/* The SIERRA_NET_USBCTL_BUF_LEN defines a buffer size allocated for control + * message reception ... and thus the max. received packet. + * (May be the cause for parse_hip returning -EINVAL) + */ +#define SIERRA_NET_USBCTL_BUF_LEN 1024 + +/* The SIERRA_NET_RX_URB_SZ defines the receive urb size + * for optimal throughput. + */ +#define SIERRA_NET_RX_URB_SZ 1540 + +/* list of interface numbers - used for constructing interface lists */ +struct sierra_net_iface_info { + const u32 infolen; /* number of interface numbers on list */ + const u8 *ifaceinfo; /* pointer to the array holding the numbers */ +}; + +struct sierra_net_info_data { + u16 rx_urb_size; + struct sierra_net_iface_info whitelist; +}; + +/* Private data structure */ +struct sierra_net_data { + + u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */ + + u16 link_up; /* air link up or down */ + u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */ + + u8 sync_msg[4]; /* SYNC message */ + u8 shdwn_msg[4]; /* Shutdown message */ + + /* Backpointer to the container */ + struct usbnet *usbnet; + + u8 ifnum; /* interface number */ + +/* Bit masks, must be a power of 2 */ +#define SIERRA_NET_EVENT_RESP_AVAIL 0x01 +#define SIERRA_NET_TIMER_EXPIRY 0x02 + unsigned long kevent_flags; + struct work_struct sierra_net_kevent; + struct timer_list sync_timer; /* For retrying SYNC sequence */ +}; + +struct param { + int is_present; + union { + void *ptr; + u32 dword; + u16 word; + u8 byte; + }; +}; + +/* HIP message type */ +#define SIERRA_NET_HIP_EXTENDEDID 0x7F +#define SIERRA_NET_HIP_HSYNC_ID 0x60 /* Modem -> host */ +#define SIERRA_NET_HIP_RESTART_ID 0x62 /* Modem -> host */ +#define SIERRA_NET_HIP_MSYNC_ID 0x20 /* Host -> modem */ +#define SIERRA_NET_HIP_SHUTD_ID 0x26 /* Host -> modem */ + +#define SIERRA_NET_HIP_EXT_IP_IN_ID 0x0202 +#define SIERRA_NET_HIP_EXT_IP_OUT_ID 0x0002 + +/* 3G UMTS Link Sense Indication definitions */ +#define SIERRA_NET_HIP_LSI_UMTSID 0x78 + +/* Reverse Channel Grant Indication HIP message */ +#define SIERRA_NET_HIP_RCGI 0x64 + +/* LSI Protocol types */ +#define SIERRA_NET_PROTOCOL_UMTS 0x01 +/* LSI Coverage */ +#define SIERRA_NET_COVERAGE_NONE 0x00 +#define SIERRA_NET_COVERAGE_NOPACKET 0x01 + +/* LSI Session */ +#define SIERRA_NET_SESSION_IDLE 0x00 +/* LSI Link types */ +#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00 +#define SIERRA_NET_AS_LINK_TYPE_IPv6 0x02 + +struct lsi_umts { + u8 protocol; + u8 unused1; + __be16 length; + /* eventually use a union for the rest - assume umts for now */ + u8 coverage; + u8 unused2[41]; + u8 session_state; + u8 unused3[33]; + u8 link_type; + u8 pdp_addr_len; /* NW-supplied PDP address len */ + u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */ + u8 unused4[23]; + u8 dns1_addr_len; /* NW-supplied 1st DNS address len (bigendian) */ + u8 dns1_addr[16]; /* NW-supplied 1st DNS address */ + u8 dns2_addr_len; /* NW-supplied 2nd DNS address len */ + u8 dns2_addr[16]; /* NW-supplied 2nd DNS address (bigendian)*/ + u8 wins1_addr_len; /* NW-supplied 1st Wins address len */ + u8 wins1_addr[16]; /* NW-supplied 1st Wins address (bigendian)*/ + u8 wins2_addr_len; /* NW-supplied 2nd Wins address len */ + u8 wins2_addr[16]; /* NW-supplied 2nd Wins address (bigendian) */ + u8 unused5[4]; + u8 gw_addr_len; /* NW-supplied GW address len */ + u8 gw_addr[16]; /* NW-supplied GW address (bigendian) */ + u8 reserved[8]; +} __packed; + +#define SIERRA_NET_LSI_COMMON_LEN 4 +#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts)) +#define SIERRA_NET_LSI_UMTS_STATUS_LEN \ + (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN) + +/* Forward definitions */ +static void sierra_sync_timer(unsigned long syncdata); +static int sierra_net_change_mtu(struct net_device *net, int new_mtu); + +/* Our own net device operations structure */ +static const struct net_device_ops sierra_net_device_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = sierra_net_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +/* get private data associated with passed in usbnet device */ +static inline struct sierra_net_data *sierra_net_get_private(struct usbnet *dev) +{ + return (struct sierra_net_data *)dev->data[0]; +} + +/* set private data associated with passed in usbnet device */ +static inline void sierra_net_set_private(struct usbnet *dev, + struct sierra_net_data *priv) +{ + dev->data[0] = (unsigned long)priv; +} + +/* is packet IP */ +static inline int is_ip(struct sk_buff *skb) +{ + return ((skb->protocol == cpu_to_be16(ETH_P_IP)) || + (skb->protocol == cpu_to_be16(ETH_P_IPV6))); +} + +/* + * check passed in packet and make sure that: + * - it is linear (no scatter/gather) + * - it is ethernet (mac_header properly set) + */ +static int check_ethip_packet(struct sk_buff *skb, struct usbnet *dev) +{ + skb_reset_mac_header(skb); /* ethernet header */ + + if (skb_is_nonlinear(skb)) { + netdev_err(dev->net, "Non linear buffer-dropping\n"); + return 0; + } + + if (!pskb_may_pull(skb, ETH_HLEN)) + return 0; + skb->protocol = eth_hdr(skb)->h_proto; + + return 1; +} + +static const u8 *save16bit(struct param *p, const u8 *datap) +{ + p->is_present = 1; + p->word = get_unaligned_be16(datap); + return datap + sizeof(p->word); +} + +static const u8 *save8bit(struct param *p, const u8 *datap) +{ + p->is_present = 1; + p->byte = *datap; + return datap + sizeof(p->byte); +} + +/*----------------------------------------------------------------------------* + * BEGIN HIP * + *----------------------------------------------------------------------------*/ +/* HIP header */ +#define SIERRA_NET_HIP_HDR_LEN 4 +/* Extended HIP header */ +#define SIERRA_NET_HIP_EXT_HDR_LEN 6 + +struct hip_hdr { + int hdrlen; + struct param payload_len; + struct param msgid; + struct param msgspecific; + struct param extmsgid; +}; + +static int parse_hip(const u8 *buf, const u32 buflen, struct hip_hdr *hh) +{ + const u8 *curp = buf; + int padded; + + if (buflen < SIERRA_NET_HIP_HDR_LEN) + return -EPROTO; + + curp = save16bit(&hh->payload_len, curp); + curp = save8bit(&hh->msgid, curp); + curp = save8bit(&hh->msgspecific, curp); + + padded = hh->msgid.byte & 0x80; + hh->msgid.byte &= 0x7F; /* 7 bits */ + + hh->extmsgid.is_present = (hh->msgid.byte == SIERRA_NET_HIP_EXTENDEDID); + if (hh->extmsgid.is_present) { + if (buflen < SIERRA_NET_HIP_EXT_HDR_LEN) + return -EPROTO; + + hh->payload_len.word &= 0x3FFF; /* 14 bits */ + + curp = save16bit(&hh->extmsgid, curp); + hh->extmsgid.word &= 0x03FF; /* 10 bits */ + + hh->hdrlen = SIERRA_NET_HIP_EXT_HDR_LEN; + } else { + hh->payload_len.word &= 0x07FF; /* 11 bits */ + hh->hdrlen = SIERRA_NET_HIP_HDR_LEN; + } + + if (padded) { + hh->hdrlen++; + hh->payload_len.word--; + } + + /* if real packet shorter than the claimed length */ + if (buflen < (hh->hdrlen + hh->payload_len.word)) + return -EINVAL; + + return 0; +} + +static void build_hip(u8 *buf, const u16 payloadlen, + struct sierra_net_data *priv) +{ + /* the following doesn't have the full functionality. We + * currently build only one kind of header, so it is faster this way + */ + put_unaligned_be16(payloadlen, buf); + memcpy(buf+2, priv->tx_hdr_template, sizeof(priv->tx_hdr_template)); +} +/*----------------------------------------------------------------------------* + * END HIP * + *----------------------------------------------------------------------------*/ +/* This should come out before going to kernel.org */ +static void sierra_net_printk_buf(u8 *buf, u16 len) +{ +#ifdef VERBOSE + u16 i; + u16 k; + + for (i = k = 0; i < len / 4; i++, k += 4) { + printk(KERN_DEBUG "%02x%02x%02x%02x ", + buf[k+0], buf[k+1], buf[k+2], buf[k+3]); + } + + for (; k < len; k++) + printk(KERN_DEBUG "%02x", buf[k]); + + printk("\n"); +#endif +} + +static int sierra_net_send_cmd(struct usbnet *dev, + u8 *cmd, int cmdlen, const char * cmd_name) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + int status; + + usb_autopm_get_interface(dev->intf); + status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), + USB_CDC_SEND_ENCAPSULATED_COMMAND, + USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0, + priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT); + usb_autopm_put_interface(dev->intf); + + if (status != cmdlen && status != -ENODEV) + netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status); + + return status; +} + +static int sierra_net_send_sync(struct usbnet *dev) +{ + int status; + struct sierra_net_data *priv = sierra_net_get_private(dev); + + dev_dbg(&dev->udev->dev, "%s", __func__); + + status = sierra_net_send_cmd(dev, priv->sync_msg, + sizeof(priv->sync_msg), "SYNC"); + return status; +} + +static void sierra_net_send_shutdown(struct usbnet *dev) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + + dev_dbg(&dev->udev->dev, "%s", __func__); + + sierra_net_send_cmd(dev, priv->shdwn_msg, + sizeof(priv->shdwn_msg), "Shutdown"); +} + +static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix) +{ + dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix); + priv->tx_hdr_template[0] = 0x3F; + priv->tx_hdr_template[1] = ctx_ix; + *((u16 *)&priv->tx_hdr_template[2]) = + cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID); +} + +static inline int sierra_net_is_valid_addrlen(u8 len) +{ + return (len == sizeof(struct in_addr)); +} + +static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen) +{ + struct lsi_umts *lsi = (struct lsi_umts *)data; + + if (datalen < sizeof(struct lsi_umts)) { + netdev_err(dev->net, "%s: Data length %d, exp %Zu\n", + __func__, datalen, + sizeof(struct lsi_umts)); + return -1; + } + + if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) { + netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", + __func__, be16_to_cpu(lsi->length), + (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN); + return -1; + } + + /* Validate the protocol - only support UMTS for now */ + if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { + netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", + lsi->protocol); + return -1; + } + + /* Validate the link type */ + if ((lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) && + (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv6)) { + netdev_err(dev->net, "Link unavailable: 0x%02x", + lsi->link_type); + return 0; + } + + /* Validate the coverage */ + if (lsi->coverage == SIERRA_NET_COVERAGE_NONE + || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { + netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage); + return 0; + } + + /* Validate the session state */ + if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { + netdev_err(dev->net, "Session idle, 0x%02x\n", + lsi->session_state); + return 0; + } + + /* Set link_sense true */ + return 1; +} + +static void sierra_net_handle_lsi(struct usbnet *dev, char *data, + struct hip_hdr *hh) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + int link_up; + + link_up = sierra_net_parse_lsi(dev, data + hh->hdrlen, + hh->payload_len.word); + if (link_up < 0) { + netdev_err(dev->net, "Invalid LSI\n"); + return; + } + if (link_up) { + sierra_net_set_ctx_index(priv, hh->msgspecific.byte); + priv->link_up = 1; + netif_carrier_on(dev->net); + } else { + priv->link_up = 0; + netif_carrier_off(dev->net); + } +} + +static void sierra_net_dosync(struct usbnet *dev) +{ + int status; + struct sierra_net_data *priv = sierra_net_get_private(dev); + + dev_dbg(&dev->udev->dev, "%s", __func__); + + /* tell modem we are ready */ + status = sierra_net_send_sync(dev); + if (status < 0) + netdev_err(dev->net, + "Send SYNC failed, status %d\n", status); + status = sierra_net_send_sync(dev); + if (status < 0) + netdev_err(dev->net, + "Send SYNC failed, status %d\n", status); + + /* Now, start a timer and make sure we get the Restart Indication */ + priv->sync_timer.function = sierra_sync_timer; + priv->sync_timer.data = (unsigned long) dev; + priv->sync_timer.expires = jiffies + SIERRA_NET_SYNCDELAY; + add_timer(&priv->sync_timer); +} + +static void sierra_net_kevent(struct work_struct *work) +{ + struct sierra_net_data *priv = + container_of(work, struct sierra_net_data, sierra_net_kevent); + struct usbnet *dev = priv->usbnet; + int len; + int err; + u8 *buf; + u8 ifnum; + + if (test_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags)) { + clear_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags); + + /* Query the modem for the LSI message */ + buf = kzalloc(SIERRA_NET_USBCTL_BUF_LEN, GFP_KERNEL); + if (!buf) { + netdev_err(dev->net, + "failed to allocate buf for LS msg\n"); + return; + } + ifnum = priv->ifnum; + usb_autopm_get_interface(dev->intf); + len = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), + USB_CDC_GET_ENCAPSULATED_RESPONSE, + USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE, + 0, ifnum, buf, SIERRA_NET_USBCTL_BUF_LEN, + USB_CTRL_SET_TIMEOUT); + usb_autopm_put_interface(dev->intf); + + if (unlikely(len < 0)) { + netdev_err(dev->net, + "usb_control_msg failed, status %d\n", len); + } else { + struct hip_hdr hh; + + dev_dbg(&dev->udev->dev, "%s: Received status message," + " %04x bytes", __func__, len); + sierra_net_printk_buf(buf, len); + + err = parse_hip(buf, len, &hh); + if (err) { + netdev_err(dev->net, "%s: Bad packet," + " parse result %d\n", __func__, err); + kfree(buf); + return; + } + + /* Validate packet length */ + if (len != hh.hdrlen + hh.payload_len.word) { + netdev_err(dev->net, "%s: Bad packet, received" + " %d, expected %d\n", __func__, len, + hh.hdrlen + hh.payload_len.word); + kfree(buf); + return; + } + + /* Switch on received message types */ + switch (hh.msgid.byte) { + case SIERRA_NET_HIP_LSI_UMTSID: + dev_dbg(&dev->udev->dev, "LSI for ctx:%d", + hh.msgspecific.byte); + sierra_net_handle_lsi(dev, buf, &hh); + break; + case SIERRA_NET_HIP_RESTART_ID: + dev_dbg(&dev->udev->dev, "Restart reported: %d," + " stopping sync timer", + hh.msgspecific.byte); + /* Got sync resp - stop timer & clear mask */ + del_timer_sync(&priv->sync_timer); + clear_bit(SIERRA_NET_TIMER_EXPIRY, + &priv->kevent_flags); + break; + case SIERRA_NET_HIP_HSYNC_ID: + dev_dbg(&dev->udev->dev, "SYNC received"); + err = sierra_net_send_sync(dev); + if (err < 0) + netdev_err(dev->net, + "Send SYNC failed %d\n", err); + break; + case SIERRA_NET_HIP_EXTENDEDID: + netdev_err(dev->net, "Unrecognized HIP msg, " + "extmsgid 0x%04x\n", hh.extmsgid.word); + break; + case SIERRA_NET_HIP_RCGI: + /* Ignored. It is a firmware + * workaround to solve a Windows driver bug and + * may be removed in the future. + */ + break; + default: + netdev_err(dev->net, "Unrecognized HIP msg, " + "msgid 0x%02x\n", hh.msgid.byte); + break; + } + } + kfree(buf); + } + /* The sync timer bit might be set */ + if (test_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags)) { + clear_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags); + dev_dbg(&dev->udev->dev, "Deferred sync timer expiry"); + sierra_net_dosync(priv->usbnet); + } + + if (priv->kevent_flags) + dev_dbg(&dev->udev->dev, "sierra_net_kevent done, " + "kevent_flags = 0x%lx", priv->kevent_flags); +} + +static void sierra_net_defer_kevent(struct usbnet *dev, int work) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + + set_bit(work, &priv->kevent_flags); + if (!schedule_work(&priv->sierra_net_kevent)) + dev_dbg(&dev->udev->dev, "sierra_net_kevent %d may have been dropped", work); + else + dev_dbg(&dev->udev->dev, "sierra_net_kevent %d scheduled", work); +} + +/* + * Sync Retransmit Timer Handler. On expiry, kick the work queue + */ +void sierra_sync_timer(unsigned long syncdata) +{ + struct usbnet *dev = (struct usbnet *)syncdata; + + dev_dbg(&dev->udev->dev, "%s", __func__); + /* Kick the tasklet */ + sierra_net_defer_kevent(dev, SIERRA_NET_TIMER_EXPIRY); +} + +static void sierra_net_status(struct usbnet *dev, struct urb *urb) +{ + struct usb_cdc_notification *event; + + dev_dbg(&dev->udev->dev, "%s", __func__); + sierra_net_printk_buf(urb->transfer_buffer, urb->actual_length); + + if (urb->actual_length < sizeof *event) + return; + + /* Add cases to handle other standard notifications. */ + event = urb->transfer_buffer; + switch (event->bNotificationType) { + case USB_CDC_NOTIFY_NETWORK_CONNECTION: + case USB_CDC_NOTIFY_SPEED_CHANGE: + /* USB 305 sends those */ + break; + case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: + sierra_net_defer_kevent(dev, SIERRA_NET_EVENT_RESP_AVAIL); + break; + default: + netdev_err(dev->net, ": unexpected notification %02x!\n", + event->bNotificationType); + break; + } +} + +static void sierra_net_get_drvinfo(struct net_device *net, + struct ethtool_drvinfo *info) +{ + /* Inherit standard device info */ + usbnet_get_drvinfo(net, info); + strncpy(info->driver, driver_name, sizeof info->driver); + strncpy(info->version, DRIVER_VERSION, sizeof info->version); +} + +static u32 sierra_net_get_link(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + /* Report link is down whenever the interface is down */ + return sierra_net_get_private(dev)->link_up && netif_running(net); +} + +static struct ethtool_ops sierra_net_ethtool_ops = { + .get_drvinfo = sierra_net_get_drvinfo, + .get_link = sierra_net_get_link, + .get_msglevel = usbnet_get_msglevel, + .set_msglevel = usbnet_set_msglevel, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, +}; + +/* MTU can not be more than 1500 bytes, enforce it. */ +static int sierra_net_change_mtu(struct net_device *net, int new_mtu) +{ + if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU) + return -EINVAL; + + return usbnet_change_mtu(net, new_mtu); +} + +static int is_whitelisted(const u8 ifnum, + const struct sierra_net_iface_info *whitelist) +{ + if (whitelist) { + const u8 *list = whitelist->ifaceinfo; + int i; + + for (i = 0; i < whitelist->infolen; i++) { + if (list[i] == ifnum) + return 1; + } + } + return 0; +} + +static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) +{ + int result = 0; + u16 *attrdata; + + attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL); + if (!attrdata) + return -ENOMEM; + + usb_autopm_get_interface(dev->intf); + result = usb_control_msg( + dev->udev, + usb_rcvctrlpipe(dev->udev, 0), + /* _u8 vendor specific request */ + SWI_USB_REQUEST_GET_FW_ATTR, + USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */ + 0x0000, /* __u16 value not used */ + 0x0000, /* __u16 index not used */ + attrdata, /* char *data */ + sizeof(*attrdata), /* __u16 size */ + USB_CTRL_SET_TIMEOUT); /* int timeout */ + usb_autopm_put_interface(dev->intf); + + if (result < 0) { + kfree(attrdata); + return -EIO; + } + + *datap = *attrdata; + + kfree(attrdata); + return result; +} + +static int sierra_net_manage_power(struct usbnet *dev, int on) +{ + dev->intf->needs_remote_wakeup = on; + return 0; +} + +/* + * collects the bulk endpoints, the status endpoint. + */ +static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) +{ + u8 ifacenum; + u8 numendpoints; + u16 fwattr = 0; + int status; + struct ethhdr *eth; + struct sierra_net_data *priv; + static const u8 sync_tmplate[sizeof(priv->sync_msg)] = { + 0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00}; + static const u8 shdwn_tmplate[sizeof(priv->shdwn_msg)] = { + 0x00, 0x00, SIERRA_NET_HIP_SHUTD_ID, 0x00}; + + struct sierra_net_info_data *data = + (struct sierra_net_info_data *)dev->driver_info->data; + + dev_dbg(&dev->udev->dev, "%s", __func__); + + ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; + /* We only accept certain interfaces */ + if (!is_whitelisted(ifacenum, &data->whitelist)) { + dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); + return -ENODEV; + } + numendpoints = intf->cur_altsetting->desc.bNumEndpoints; + /* We have three endpoints, bulk in and out, and a status */ + if (numendpoints != 3) { + dev_err(&dev->udev->dev, "Expected 3 endpoints, found: %d", + numendpoints); + return -ENODEV; + } + /* Status endpoint set in usbnet_get_endpoints() */ + dev->status = NULL; + status = usbnet_get_endpoints(dev, intf); + if (status < 0) { + dev_err(&dev->udev->dev, "Error in usbnet_get_endpoints (%d)", + status); + return -ENODEV; + } + /* Initialize sierra private data */ + priv = kzalloc(sizeof *priv, GFP_KERNEL); + if (!priv) { + dev_err(&dev->udev->dev, "No memory"); + return -ENOMEM; + } + + priv->usbnet = dev; + priv->ifnum = ifacenum; + /* override change_mtu with our own routine - need to bound check */ + /* replace structure to our own structure where we have our own + * routine - need to bound check + */ + dev->net->netdev_ops = &sierra_net_device_ops; + + /* change MAC addr to include, ifacenum, and to be unique */ + dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); + dev->net->dev_addr[ETH_ALEN-1] = ifacenum; + + /* we will have to manufacture ethernet headers, prepare template */ + eth = (struct ethhdr *)priv->ethr_hdr_tmpl; + memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN); + eth->h_proto = cpu_to_be16(ETH_P_IP); + + /* prepare shutdown message template */ + memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg)); + /* set context index initially to 0 - prepares tx hdr template */ + sierra_net_set_ctx_index(priv, 0); + + /* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */ + dev->rx_urb_size = data->rx_urb_size; + if (dev->udev->speed != USB_SPEED_HIGH) + dev->rx_urb_size = min_t(size_t, 4096, data->rx_urb_size); + + dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; + + /* Set up the netdev */ + dev->net->flags |= IFF_NOARP; + dev->net->flags |= IFF_MULTICAST; + dev->net->ethtool_ops = &sierra_net_ethtool_ops; + netif_carrier_off(dev->net); + + sierra_net_set_private(dev, priv); + + priv->kevent_flags = 0; + + /* Use the shared workqueue */ + INIT_WORK(&priv->sierra_net_kevent, sierra_net_kevent); + + /* Only need to do this once */ + init_timer(&priv->sync_timer); + /* verify fw attributes */ + status = sierra_net_get_fw_attr(dev, &fwattr); + dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr); + if (status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_APM)) { +/******************************************************************************* + * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced + * to auto, the following needs to be compiled in. + */ +#ifdef POWER_LEVEL_AUTO + /* make power level default be 'auto' */ + dev_dbg(&dev->udev->dev, "Enabling APM"); + usb_enable_autosuspend(dev->udev); +#endif + } else { + dev_info(&intf->dev, "Disabling APM - not supported"); + usb_disable_autosuspend(dev->udev); + } + /* test whether firmware supports DHCP */ + if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) { + /* found incompatible firmware version */ + dev_err(&dev->udev->dev, "Incompatible driver and firmware" + " versions\n"); + kfree(priv); + return -ENODEV; + } + /* prepare sync message from template */ + memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); + + return 0; +} + +static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + + dev_dbg(&dev->udev->dev, "%s", __func__); + + sierra_net_set_private(dev, NULL); + + kfree(priv); +} + +static int sierra_net_open(struct usbnet *dev) +{ + dev_dbg(&dev->udev->dev, "%s", __func__); + + /* initiate the sync sequence */ + sierra_net_dosync(dev); + + return 0; +} + +static int sierra_net_stop(struct usbnet *dev) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + + dev_dbg(&dev->udev->dev, "%s", __func__); + + /* Kill the timer then flush the work queue */ + del_timer_sync(&priv->sync_timer); + + cancel_work_sync(&priv->sierra_net_kevent); + + /* tell modem we are going away */ + sierra_net_send_shutdown(dev); + + return 0; +} + +static struct sk_buff *sierra_net_skb_clone(struct usbnet *dev, + struct sk_buff *skb, int len) +{ + struct sk_buff *new_skb; + + /* clone skb */ + new_skb = skb_clone(skb, GFP_ATOMIC); + + /* remove len bytes from original */ + skb_pull(skb, len); + + /* trim next packet to it's length */ + if (new_skb) { + skb_trim(new_skb, len); + } else { + if (netif_msg_rx_err(dev)) + netdev_err(dev->net, "failed to get skb\n"); + dev->net->stats.rx_dropped++; + } + + return new_skb; +} + +/* ---------------------------- Receive data path ----------------------*/ +static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + int err; + struct hip_hdr hh; + struct sk_buff *new_skb; + struct ethhdr *eth; + struct iphdr *ip; + + dev_dbg(&dev->udev->dev, "%s", __func__); + + sierra_net_printk_buf(skb->data, skb->len); + + /* could contain multiple packets */ + while (likely(skb->len)) { + err = parse_hip(skb->data, skb->len, &hh); + if (err) { + if (netif_msg_rx_err(dev)) + netdev_err(dev->net, "Invalid HIP header %d\n", + err); + /* dev->net->stats.rx_errors incremented by caller */ + dev->net->stats.rx_length_errors++; + return 0; + } + + /* Validate Extended HIP header */ + if (!hh.extmsgid.is_present + || hh.extmsgid.word != SIERRA_NET_HIP_EXT_IP_IN_ID) { + if (netif_msg_rx_err(dev)) + netdev_err(dev->net, "HIP/ETH: Invalid pkt\n"); + + dev->net->stats.rx_frame_errors++; + /* dev->net->stats.rx_errors incremented by caller */; + return 0; + } + + skb_pull(skb, hh.hdrlen); + + /* We are going to accept this packet, prepare it */ + memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl, + ETH_HLEN); + + ip = (struct iphdr *)((char *)skb->data + ETH_HLEN); + if(ip->version == 6) { + eth = (struct ethhdr *)skb->data; + eth->h_proto = cpu_to_be16(ETH_P_IPV6); + } + + /* Last packet in batch handled by usbnet */ + if (hh.payload_len.word == skb->len) + return 1; + + new_skb = sierra_net_skb_clone(dev, skb, hh.payload_len.word); + if (new_skb) + usbnet_skb_return(dev, new_skb); + + } /* while */ + + return 0; +} + +/* ---------------------------- Transmit data path ----------------------*/ +struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) +{ + struct sierra_net_data *priv = sierra_net_get_private(dev); + u16 len; + bool need_tail; + + dev_dbg(&dev->udev->dev, "%s", __func__); + if (priv->link_up && check_ethip_packet(skb, dev) && is_ip(skb)) { + /* enough head room as is? */ + if (SIERRA_NET_HIP_EXT_HDR_LEN <= skb_headroom(skb)) { + /* Save the Eth/IP length and set up HIP hdr */ + len = skb->len; + skb_push(skb, SIERRA_NET_HIP_EXT_HDR_LEN); + /* Handle ZLP issue */ + need_tail = ((len + SIERRA_NET_HIP_EXT_HDR_LEN) + % dev->maxpacket == 0); + if (need_tail) { + if (unlikely(skb_tailroom(skb) == 0)) { + netdev_err(dev->net, "tx_fixup:" + "no room for packet\n"); + dev_kfree_skb_any(skb); + return NULL; + } else { + skb->data[skb->len] = 0; + __skb_put(skb, 1); + len = len + 1; + } + } + build_hip(skb->data, len, priv); + + sierra_net_printk_buf(skb->data, skb->len); + return skb; + } else { + /* + * compensate in the future if necessary + */ + netdev_err(dev->net, "tx_fixup: no room for HIP\n"); + } /* headroom */ + } + + if (!priv->link_up) + dev->net->stats.tx_carrier_errors++; + + /* tx_dropped incremented by usbnet */ + + /* filter the packet out, release it */ + dev_kfree_skb_any(skb); + return NULL; +} + +static int sierra_net_reset_resume(struct usb_interface *intf) +{ + struct usbnet *dev = usb_get_intfdata(intf); + netdev_err(dev->net, "%s\n", __func__); + return usbnet_resume(intf); +} + +static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; +static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { + /* .rx_urb_size = 8 * 1024, */ + .rx_urb_size = SIERRA_NET_RX_URB_SZ, + .whitelist = { + .infolen = ARRAY_SIZE(sierra_net_ifnum_list), + .ifaceinfo = sierra_net_ifnum_list + } +}; + +static const struct driver_info sierra_net_info_direct_ip = { + .description = "Sierra Wireless USB-to-WWAN Modem", + .flags = FLAG_WWAN | FLAG_SEND_ZLP, + .bind = sierra_net_bind, + .unbind = sierra_net_unbind, + .status = sierra_net_status, + .rx_fixup = sierra_net_rx_fixup, + .tx_fixup = sierra_net_tx_fixup, + .manage_power = sierra_net_manage_power, + .stop = sierra_net_stop, + .check_connect = sierra_net_open, + .data = (unsigned long)&sierra_net_info_data_direct_ip, +}; + +static const struct usb_device_id products[] = { + {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0xF3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0xF3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + + {}, /* last item */ +}; +MODULE_DEVICE_TABLE(usb, products); + +/* We are based on usbnet, so let it handle the USB driver specifics */ +static struct usb_driver sierra_net_driver = { + .name = "sierra_net", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .reset_resume = sierra_net_reset_resume, + .no_dynamic_id = 1, + .supports_autosuspend = 1, +}; + +static int __init sierra_net_init(void) +{ + BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data) + < sizeof(struct cdc_state)); + + return usb_register(&sierra_net_driver); +} + +static void __exit sierra_net_exit(void) +{ + usb_deregister(&sierra_net_driver); +} + +module_exit(sierra_net_exit); +module_init(sierra_net_init); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/package/system/spi-ks8995/Makefile b/package/system/spi-ks8995/Makefile new file mode 100644 index 0000000000..0be9fe3dc6 --- /dev/null +++ b/package/system/spi-ks8995/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=spi-ks8995 +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/spi-ks8995 + SUBMENU:=SPI Support + TITLE:=Micrel/Kendin KS8995 Ethernet switch control + FILES:=$(PKG_BUILD_DIR)/spi_ks8995.ko + KCONFIG:=CONFIG_SPI=y \ + CONFIG_SPI_MASTER=y + AUTOLOAD:=$(call AutoLoad,50,spi_ks8995) +endef + +define KernelPackage/spi-ks8995/description + Kernel module for Micrel/Kendin KS8995 ethernet switch +endef + +EXTRA_KCONFIG:= \ + CONFIG_SPI_KS8995=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,spi-ks8995)) diff --git a/package/system/spi-ks8995/src/Kconfig b/package/system/spi-ks8995/src/Kconfig new file mode 100644 index 0000000000..7859be183d --- /dev/null +++ b/package/system/spi-ks8995/src/Kconfig @@ -0,0 +1,3 @@ +config SPI_KS8995 + tristate "Micrel/Kendin KS8995 Ethernet switch" + depends on SPI diff --git a/package/system/spi-ks8995/src/Makefile b/package/system/spi-ks8995/src/Makefile new file mode 100644 index 0000000000..810c3bd1db --- /dev/null +++ b/package/system/spi-ks8995/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_SPI_KS8995} += spi_ks8995.o
\ No newline at end of file diff --git a/package/system/spi-ks8995/src/spi_ks8995.c b/package/system/spi-ks8995/src/spi_ks8995.c new file mode 100644 index 0000000000..c0dd86b4cc --- /dev/null +++ b/package/system/spi-ks8995/src/spi_ks8995.c @@ -0,0 +1,419 @@ +/* + * SPI driver for Micrel/Kendin KS8995M ethernet switch + * + * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org> + * + * This file was based on: drivers/spi/at25.c + * Copyright (C) 2006 David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/device.h> + +#include <linux/spi/spi.h> + +#define DRV_VERSION "0.1.1" +#define DRV_DESC "Micrel/Kendin KS8995 Ethernet switch SPI driver" + +/*-------------------------------------------------------------------------*/ + +#define KS8995_REG_ID0 0x00 /* Chip ID0 */ +#define KS8995_REG_ID1 0x01 /* Chip ID1 */ + +#define KS8995_REG_GC0 0x02 /* Global Control 0 */ +#define KS8995_REG_GC1 0x03 /* Global Control 1 */ +#define KS8995_REG_GC2 0x04 /* Global Control 2 */ +#define KS8995_REG_GC3 0x05 /* Global Control 3 */ +#define KS8995_REG_GC4 0x06 /* Global Control 4 */ +#define KS8995_REG_GC5 0x07 /* Global Control 5 */ +#define KS8995_REG_GC6 0x08 /* Global Control 6 */ +#define KS8995_REG_GC7 0x09 /* Global Control 7 */ +#define KS8995_REG_GC8 0x0a /* Global Control 8 */ +#define KS8995_REG_GC9 0x0b /* Global Control 9 */ + +#define KS8995_REG_PC(p,r) ((0x10 * p) + r) /* Port Control */ +#define KS8995_REG_PS(p,r) ((0x10 * p) + r + 0xe) /* Port Status */ + +#define KS8995_REG_TPC0 0x60 /* TOS Priority Control 0 */ +#define KS8995_REG_TPC1 0x61 /* TOS Priority Control 1 */ +#define KS8995_REG_TPC2 0x62 /* TOS Priority Control 2 */ +#define KS8995_REG_TPC3 0x63 /* TOS Priority Control 3 */ +#define KS8995_REG_TPC4 0x64 /* TOS Priority Control 4 */ +#define KS8995_REG_TPC5 0x65 /* TOS Priority Control 5 */ +#define KS8995_REG_TPC6 0x66 /* TOS Priority Control 6 */ +#define KS8995_REG_TPC7 0x67 /* TOS Priority Control 7 */ + +#define KS8995_REG_MAC0 0x68 /* MAC address 0 */ +#define KS8995_REG_MAC1 0x69 /* MAC address 1 */ +#define KS8995_REG_MAC2 0x6a /* MAC address 2 */ +#define KS8995_REG_MAC3 0x6b /* MAC address 3 */ +#define KS8995_REG_MAC4 0x6c /* MAC address 4 */ +#define KS8995_REG_MAC5 0x6d /* MAC address 5 */ + +#define KS8995_REG_IAC0 0x6e /* Indirect Access Control 0 */ +#define KS8995_REG_IAC1 0x6f /* Indirect Access Control 0 */ + +#define KS8995_REG_IAD7 0x70 /* Indirect Access Data 7 */ +#define KS8995_REG_IAD6 0x71 /* Indirect Access Data 6 */ +#define KS8995_REG_IAD5 0x72 /* Indirect Access Data 5 */ +#define KS8995_REG_IAD4 0x73 /* Indirect Access Data 4 */ +#define KS8995_REG_IAD3 0x74 /* Indirect Access Data 3 */ +#define KS8995_REG_IAD2 0x75 /* Indirect Access Data 2 */ +#define KS8995_REG_IAD1 0x76 /* Indirect Access Data 1 */ +#define KS8995_REG_IAD0 0x77 /* Indirect Access Data 0 */ + +#define KS8995_REGS_SIZE 0x80 + +#define ID1_CHIPID_M 0xf +#define ID1_CHIPID_S 4 +#define ID1_REVISION_M 0x7 +#define ID1_REVISION_S 1 +#define ID1_START_SW 1 /* start the switch */ + +#define FAMILY_KS8995 0x95 +#define CHIPID_M 0 + +#define KS8995_CMD_WRITE 0x02U +#define KS8995_CMD_READ 0x03U + +#define KS8995_RESET_DELAY 10 /* usec */ + +/*-------------------------------------------------------------------------*/ + +struct ks8995_pdata { + /* not yet implemented */ +}; + +struct ks8995_switch { + struct spi_device *spi; + struct mutex lock; + struct ks8995_pdata *pdata; +}; + +/*-------------------------------------------------------------------------*/ + +static inline u8 get_chip_id(u8 val) +{ + return ((val >> ID1_CHIPID_S) & ID1_CHIPID_M); +} + +static inline u8 get_chip_rev(u8 val) +{ + return ((val >> ID1_REVISION_S) & ID1_REVISION_M); +} + +/*-------------------------------------------------------------------------*/ + +static int ks8995_read(struct ks8995_switch *ks, char *buf, + unsigned offset, size_t count) +{ + u8 cmd[2]; + struct spi_transfer t[2]; + struct spi_message m; + int err; + + spi_message_init(&m); + + memset(&t, 0, sizeof(t)); + + t[0].tx_buf = cmd; + t[0].len = sizeof(cmd); + spi_message_add_tail(&t[0], &m); + + t[1].rx_buf = buf; + t[1].len = count; + spi_message_add_tail(&t[1], &m); + + cmd[0] = KS8995_CMD_READ; + cmd[1] = offset; + + mutex_lock(&ks->lock); + err = spi_sync(ks->spi, &m); + mutex_unlock(&ks->lock); + + return err ? err : count; +} + + +static int ks8995_write(struct ks8995_switch *ks, char *buf, + unsigned offset, size_t count) +{ + u8 cmd[2]; + struct spi_transfer t[2]; + struct spi_message m; + int err; + + spi_message_init(&m); + + memset(&t, 0, sizeof(t)); + + t[0].tx_buf = cmd; + t[0].len = sizeof(cmd); + spi_message_add_tail(&t[0], &m); + + t[1].tx_buf = buf; + t[1].len = count; + spi_message_add_tail(&t[1], &m); + + cmd[0] = KS8995_CMD_WRITE; + cmd[1] = offset; + + mutex_lock(&ks->lock); + err = spi_sync(ks->spi, &m); + mutex_unlock(&ks->lock); + + return err ? err : count; +} + +static inline int ks8995_read_reg(struct ks8995_switch *ks, u8 addr, u8 *buf) +{ + return (ks8995_read(ks, buf, addr, 1) != 1); +} + +static inline int ks8995_write_reg(struct ks8995_switch *ks, u8 addr, u8 val) +{ + char buf = val; + + return (ks8995_write(ks, &buf, addr, 1) != 1); +} + +/*-------------------------------------------------------------------------*/ + +#if 0 +static int ks8995_setup(struct spi_device *spi) +{ + struct ks8995_switch *ks; + u8 t; + + ks = dev_get_drvdata(&spi->dev); + + ks8995_write_reg(ks, KS8995_REG_GC0, 0x4c); + ks8995_write_reg(ks, KS8995_REG_GC1, 0x05); + + ks8995_read_reg(ks, KS8995_REG_GC2, &t); + ks8995_write_reg(ks, KS8995_REG_GC2, t | 1); + + ks8995_write_reg(ks, KS8995_REG_GC4, 0x20); + + ks8995_write_reg(ks, KS8995_REG_PC(1,0), 0x61); + ks8995_write_reg(ks, KS8995_REG_PC(2,0), 0x61); + ks8995_write_reg(ks, KS8995_REG_PC(3,0), 0x61); + ks8995_write_reg(ks, KS8995_REG_PC(4,0), 0x61); + ks8995_write_reg(ks, KS8995_REG_PC(5,0), 0x61); + + ks8995_write_reg(ks, KS8995_REG_PC(5,11), 0x18); + + ks8995_write_reg(ks, KS8995_REG_TPC0, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC1, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC2, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC3, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC4, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC5, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC6, 0xff); + ks8995_write_reg(ks, KS8995_REG_TPC7, 0xfe); + + return 0; +} +#endif + +static int ks8995_stop(struct ks8995_switch *ks) +{ + return ks8995_write_reg(ks, KS8995_REG_ID1, 0); +} + +static int ks8995_start(struct ks8995_switch *ks) +{ + return ks8995_write_reg(ks, KS8995_REG_ID1, 1); +} + +static int ks8995_reset(struct ks8995_switch *ks) +{ + int err; + + err = ks8995_stop(ks); + if (err) + return err; + + udelay(KS8995_RESET_DELAY); + + return ks8995_start(ks); +} + +/*-------------------------------------------------------------------------*/ + +static int ks8995_registers_read(struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +{ + struct device *dev; + struct ks8995_switch *ks8995; + + dev = container_of(kobj, struct device, kobj); + ks8995 = dev_get_drvdata(dev); + + if (unlikely(off > KS8995_REGS_SIZE)) + return 0; + + if ((off + count) > KS8995_REGS_SIZE) + count = KS8995_REGS_SIZE - off; + + if (unlikely(!count)) + return count; + + return ks8995_read(ks8995, buf, off, count); +} + + +static int ks8995_registers_write(struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +{ + struct device *dev; + struct ks8995_switch *ks8995; + + dev = container_of(kobj, struct device, kobj); + ks8995 = dev_get_drvdata(dev); + + if (unlikely(off >= KS8995_REGS_SIZE)) + return -EFBIG; + + if ((off + count) > KS8995_REGS_SIZE) + count = KS8995_REGS_SIZE - off; + + if (unlikely(!count)) + return count; + + return ks8995_write(ks8995, buf, off, count); +} + + +static struct bin_attribute ks8995_registers_attr = { + .attr = { + .name = "registers", + .mode = S_IRUSR | S_IWUSR, + }, + .size = KS8995_REGS_SIZE, + .read = ks8995_registers_read, + .write = ks8995_registers_write, +}; + +/*-------------------------------------------------------------------------*/ + +static int __devinit ks8995_probe(struct spi_device *spi) +{ + struct ks8995_switch *ks; + struct ks8995_pdata *pdata; + u8 ids[2]; + int err; + + /* Chip description */ + pdata = spi->dev.platform_data; + + ks = kzalloc(sizeof(*ks), GFP_KERNEL); + if (!ks) { + dev_err(&spi->dev, "no memory for private data\n"); + return-ENOMEM; + } + + mutex_init(&ks->lock); + ks->pdata = pdata; + ks->spi = spi_dev_get(spi); + dev_set_drvdata(&spi->dev, ks); + + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + err = spi_setup(spi); + if (err) { + dev_err(&spi->dev, "spi_setup failed, err=%d \n", err); + goto err_drvdata; + } + + err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids)); + if (err < 0) { + dev_err(&spi->dev, "unable to read id registers, err=%d \n", + err); + goto err_drvdata; + } + + switch (ids[0]) { + case FAMILY_KS8995: + break; + default: + dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]); + err = -ENODEV; + goto err_drvdata; + } + + err = ks8995_reset(ks); + if (err) + goto err_drvdata; + + err = sysfs_create_bin_file(&spi->dev.kobj, &ks8995_registers_attr); + if (err) { + dev_err(&spi->dev, "unable to create sysfs file, err=%d\n", + err); + goto err_drvdata; + } + + dev_info(&spi->dev, "KS89%02X device found, Chip ID:%01x, " + "Revision:%01x\n", ids[0], + get_chip_id(ids[1]), get_chip_rev(ids[1])); + + return 0; + +err_drvdata: + dev_set_drvdata(&spi->dev, NULL); + kfree(ks); + return err; +} + +static int __devexit ks8995_remove(struct spi_device *spi) +{ + struct ks8995_data *ks8995; + + ks8995 = dev_get_drvdata(&spi->dev); + sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr); + + dev_set_drvdata(&spi->dev, NULL); + kfree(ks8995); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct spi_driver ks8995_driver = { + .driver = { + .name = "spi-ks8995", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ks8995_probe, + .remove = __devexit_p(ks8995_remove), +}; + +static int __init ks8995_init(void) +{ + printk(KERN_INFO DRV_DESC " version " DRV_VERSION"\n"); + + return spi_register_driver(&ks8995_driver); +} +module_init(ks8995_init); + +static void __exit ks8995_exit(void) +{ + spi_unregister_driver(&ks8995_driver); +} +module_exit(ks8995_exit); + +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); +MODULE_LICENSE("GPL v2"); + diff --git a/package/system/spidev_test/Makefile b/package/system/spidev_test/Makefile new file mode 100644 index 0000000000..807039a1f5 --- /dev/null +++ b/package/system/spidev_test/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (C) 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=spidev-test +PKG_RELEASE:=$(LINUX_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/spidev-test + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+kmod-spi-dev + TITLE:=SPI testing utility + VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE) + URL:=http://www.kernel.org + MAINTAINER:=Florian Fainelli <florian@openwrt.org> +endef + +define Package/spidev-test/description + SPI testing utility. +endef + +define Build/Prepare +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/spidev_test \ + $(LINUX_DIR)/Documentation/spi/spidev_test.c +endef + +define Package/spidev-test/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/spidev_test $(1)/sbin/ +endef + +$(eval $(call BuildPackage,spidev-test)) diff --git a/package/system/vsc73x5-ucode/Makefile b/package/system/vsc73x5-ucode/Makefile new file mode 100644 index 0000000000..3a07121107 --- /dev/null +++ b/package/system/vsc73x5-ucode/Makefile @@ -0,0 +1,94 @@ +# +# Copyright (C) 2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=vsc73x5-ucode +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + +PKG_SOURCE:=vsc73x5-ucode.tar.bz2 +PKG_BUILD_DIR:=$(BUILD_DIR)/vsc73x5-ucode + +PKG_MD5SUM:=b32e3debcd118f263c79199a7b5afa68 + +include $(INCLUDE_DIR)/package.mk + +define Package/vsc73x5-defaults + SECTION:=net + CATEGORY:=Network + DEPENDS:=@TARGET_ar71xx + DEFAULT:=n + TITLE:=$(1) +endef + +define Package/vsc73x5/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(2) $(1)/lib/firmware/$(3) +endef + +define Package/vsc7385-ucode-ap83 + $(call Package/vsc73x5-defaults,Vitesse VSC7385 microcode for the Atheros AP83 boards) +endef + +define Package/vsc7385-ucode-ap83/description + This package contains the Atheros AP83 board specific microcode for + the Vitesse VSC7385 ethernet switch. +endef + +define Package/vsc7385-ucode-ap83/install + $(call Package/vsc73x5/install,$(1),g5_Plus1_2_31_unmanaged_Atheros_v3.bin,vsc7385_ucode_ap83.bin) +endef + +define Package/vsc7395-ucode-ap83 + $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros AP83 boards) +endef + +define Package/vsc7395-ucode-ap83/description + This package contains the Atheros AP83 board specific microcode for + the Vitesse VSC7395 ethernet switch. +endef + +define Package/vsc7395-ucode-ap83/install + $(call Package/vsc73x5/install,$(1),g5_Plus1_2_31_unmanaged_Atheros_v4.bin,vsc7395_ucode_ap83.bin) +endef + +define Package/vsc7385-ucode-pb44 + $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros PB44 boards) +endef + +define Package/vsc7385-ucode-pb44/description + This package contains the Atheros PB44 board specific microcode for + the Vitesse VSC7385 ethernet switch. +endef + +define Package/vsc7385-ucode-pb44/install + $(call Package/vsc73x5/install,$(1),g5_Plus1_2_29b_unmanaged_Atheros_v5.bin,vsc7385_ucode_pb44.bin) +endef + +define Package/vsc7395-ucode-pb44 + $(call Package/vsc73x5-defaults, Vitesse VSC7395 microcode for the Atheros PB44 boards) +endef + +define Package/vsc7395-ucode-pb44/description + This package contains the Atheros AP83 board specific microcode for + the Vitesse VSC7395 ethernet switch. +endef + +define Package/vsc7395-ucode-pb44/install + $(call Package/vsc73x5/install,$(1),g5e_Plus1_2_29a_unmanaged_Atheros_v3.bin,vsc7395_ucode_pb44.bin) +endef + +define Build/Compile + +endef + +$(eval $(call BuildPackage,vsc7385-ucode-ap83)) +$(eval $(call BuildPackage,vsc7395-ucode-ap83)) +$(eval $(call BuildPackage,vsc7385-ucode-pb44)) +$(eval $(call BuildPackage,vsc7395-ucode-pb44)) diff --git a/package/system/vsc73x5-ucode/files/Makefile b/package/system/vsc73x5-ucode/files/Makefile new file mode 100644 index 0000000000..550f51df79 --- /dev/null +++ b/package/system/vsc73x5-ucode/files/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +CC:=gcc +OBJCOPY:=objcopy + +all: g5_Plus1_2_31_unmanaged_Atheros_v3.bin \ + g5_Plus1_2_31_unmanaged_Atheros_v4.bin \ + g5_Plus1_2_29b_unmanaged_Atheros_v5.bin \ + g5e_Plus1_2_29a_unmanaged_Atheros_v3.bin + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ + +%.bin: %.o + $(OBJCOPY) -O binary -j .data $^ $@ diff --git a/package/system/w1-gpio-custom/Makefile b/package/system/w1-gpio-custom/Makefile new file mode 100644 index 0000000000..bf50d1a50f --- /dev/null +++ b/package/system/w1-gpio-custom/Makefile @@ -0,0 +1,54 @@ +# +# Copyright (C) 2008-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=w1-gpio-custom +PKG_RELEASE:=3 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/w1-gpio-custom + SUBMENU:=W1 support + TITLE:=Custom GPIO-based 1-wire device + DEPENDS:=kmod-w1 +kmod-w1-master-gpio + FILES:=$(PKG_BUILD_DIR)/w1-gpio-custom.ko + KCONFIG:= +endef + +define KernelPackage/w1-gpio-custom/description + Kernel module to register a custom w1-gpio platform device. +endef + +EXTRA_KCONFIG:= \ + CONFIG_W1_MASTER_GPIO_CUSTOM=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,w1-gpio-custom)) + diff --git a/package/system/w1-gpio-custom/src/Kconfig b/package/system/w1-gpio-custom/src/Kconfig new file mode 100644 index 0000000000..74b9226c5c --- /dev/null +++ b/package/system/w1-gpio-custom/src/Kconfig @@ -0,0 +1,4 @@ +config W1_MASTER_GPIO_CUSTOM + tristate "Custom GPIO-based W1 driver" + depends on GENERIC_GPIO + select W1_GPIO
\ No newline at end of file diff --git a/package/system/w1-gpio-custom/src/Makefile b/package/system/w1-gpio-custom/src/Makefile new file mode 100644 index 0000000000..6a527432c1 --- /dev/null +++ b/package/system/w1-gpio-custom/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_W1_MASTER_GPIO_CUSTOM} += w1-gpio-custom.o
\ No newline at end of file diff --git a/package/system/w1-gpio-custom/src/w1-gpio-custom.c b/package/system/w1-gpio-custom/src/w1-gpio-custom.c new file mode 100644 index 0000000000..96cfcabc61 --- /dev/null +++ b/package/system/w1-gpio-custom/src/w1-gpio-custom.c @@ -0,0 +1,185 @@ +/* + * Custom GPIO-based W1 driver + * + * Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org> + * Copyright (C) 2008 Bifferos <bifferos at yahoo.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * --------------------------------------------------------------------------- + * + * The behaviour of this driver can be altered by setting some parameters + * from the insmod command line. + * + * The following parameters are adjustable: + * + * bus0 These four arguments must be arrays of + * bus1 3 unsigned integers as follows: + * bus2 + * bus3 <id>,<pin>,<od> + * + * where: + * + * <id> ID to used as device_id for the corresponding bus (required) + * <sda> GPIO pin ID of data pin (required) + * <od> Pin is configured as open drain. + * + * See include/w1-gpio.h for more information about the parameters. + * + * If this driver is built into the kernel, you can use the following kernel + * command line parameters, with the same values as the corresponding module + * parameters listed above: + * + * w1-gpio-custom.bus0 + * w1-gpio-custom.bus1 + * w1-gpio-custom.bus2 + * w1-gpio-custom.bus3 + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <linux/w1-gpio.h> + +#define DRV_NAME "w1-gpio-custom" +#define DRV_DESC "Custom GPIO-based W1 driver" +#define DRV_VERSION "0.1.1" + +#define PFX DRV_NAME ": " + +#define BUS_PARAM_ID 0 +#define BUS_PARAM_PIN 1 +#define BUS_PARAM_OD 2 + +#define BUS_PARAM_REQUIRED 3 +#define BUS_PARAM_COUNT 3 +#define BUS_COUNT_MAX 4 + +static unsigned int bus0[BUS_PARAM_COUNT] __initdata; +static unsigned int bus1[BUS_PARAM_COUNT] __initdata; +static unsigned int bus2[BUS_PARAM_COUNT] __initdata; +static unsigned int bus3[BUS_PARAM_COUNT] __initdata; + +static unsigned int bus_nump[BUS_COUNT_MAX] __initdata; + +#define BUS_PARM_DESC " config -> id,pin,od" + +module_param_array(bus0, uint, &bus_nump[0], 0); +MODULE_PARM_DESC(bus0, "bus0" BUS_PARM_DESC); +module_param_array(bus1, uint, &bus_nump[1], 0); +MODULE_PARM_DESC(bus1, "bus1" BUS_PARM_DESC); +module_param_array(bus2, uint, &bus_nump[2], 0); +MODULE_PARM_DESC(bus2, "bus2" BUS_PARM_DESC); +module_param_array(bus3, uint, &bus_nump[3], 0); +MODULE_PARM_DESC(bus3, "bus3" BUS_PARM_DESC); + +static struct platform_device *devices[BUS_COUNT_MAX]; +static unsigned int nr_devices; + +static void w1_gpio_custom_cleanup(void) +{ + int i; + + for (i = 0; i < nr_devices; i++) + if (devices[i]) + platform_device_put(devices[i]); +} + +static int __init w1_gpio_custom_add_one(unsigned int id, unsigned int *params) +{ + struct platform_device *pdev; + struct w1_gpio_platform_data pdata; + int err; + + if (!bus_nump[id]) + return 0; + + if (bus_nump[id] < BUS_PARAM_REQUIRED) { + printk(KERN_ERR PFX "not enough parameters for bus%d\n", id); + err = -EINVAL; + goto err; + } + + pdev = platform_device_alloc("w1-gpio", params[BUS_PARAM_ID]); + if (!pdev) { + err = -ENOMEM; + goto err; + } + + pdata.pin = params[BUS_PARAM_PIN]; + pdata.is_open_drain = params[BUS_PARAM_OD] ? 1:0; + pdata.enable_external_pullup = NULL; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put; + + err = platform_device_add(pdev); + if (err) + goto err_put; + + devices[nr_devices++] = pdev; + return 0; + + err_put: + platform_device_put(pdev); + err: + return err; +} + +static int __init w1_gpio_custom_probe(void) +{ + int err; + + nr_devices = 0; + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); + + err = w1_gpio_custom_add_one(0, bus0); + if (err) goto err; + + err = w1_gpio_custom_add_one(1, bus1); + if (err) goto err; + + err = w1_gpio_custom_add_one(2, bus2); + if (err) goto err; + + err = w1_gpio_custom_add_one(3, bus3); + if (err) goto err; + + if (!nr_devices) { + printk(KERN_ERR PFX "no bus parameter(s) specified\n"); + err = -ENODEV; + goto err; + } + + return 0; + +err: + w1_gpio_custom_cleanup(); + return err; +} + +#ifdef MODULE +static int __init w1_gpio_custom_init(void) +{ + return w1_gpio_custom_probe(); +} +module_init(w1_gpio_custom_init); + +static void __exit w1_gpio_custom_exit(void) +{ + w1_gpio_custom_cleanup(); +} +module_exit(w1_gpio_custom_exit); +#else +subsys_initcall(w1_gpio_custom_probe); +#endif /* MODULE*/ + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Bifferos <bifferos at yahoo.co.uk >"); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); diff --git a/package/system/wrt55agv2-spidevs/Makefile b/package/system/wrt55agv2-spidevs/Makefile new file mode 100644 index 0000000000..236c9a3be3 --- /dev/null +++ b/package/system/wrt55agv2-spidevs/Makefile @@ -0,0 +1,53 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=wrt55agv2-spidevs +PKG_RELEASE:=1 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/wrt55agv2-spidevs + SUBMENU:=Other modules + TITLE:=WRT55AG v2 SPI devices support + DEPENDS:=@TARGET_atheros +kmod-spi-gpio-old +kmod-spi-ks8995 + FILES:=$(PKG_BUILD_DIR)/wrt55agv2_spidevs.ko +endef + +define KernelPackage/wrt55agv2-spidevs/description + Kernel module for the SPI devices on the WRT55AG v2 board. +endef + +EXTRA_KCONFIG:= \ + CONFIG_WRT55AGV2_SPIDEVS=m + +EXTRA_CFLAGS:= \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ + $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ + +MAKE_OPTS:= \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + SUBDIRS="$(PKG_BUILD_DIR)" \ + EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ + LINUXINCLUDE="-I$(LINUX_DIR)/include -I$(LINUX_DIR)/arch/mips/include -include generated/autoconf.h" \ + $(EXTRA_KCONFIG) + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" \ + $(MAKE_OPTS) \ + modules +endef + +$(eval $(call KernelPackage,wrt55agv2-spidevs)) diff --git a/package/system/wrt55agv2-spidevs/src/Kconfig b/package/system/wrt55agv2-spidevs/src/Kconfig new file mode 100644 index 0000000000..75e8242be7 --- /dev/null +++ b/package/system/wrt55agv2-spidevs/src/Kconfig @@ -0,0 +1,3 @@ +config WRT55AGV2_SPIDEVS + tristate "SPI device support for the WRT55AG v2 board" + depends on SPI && MIPS_ATHEROS diff --git a/package/system/wrt55agv2-spidevs/src/Makefile b/package/system/wrt55agv2-spidevs/src/Makefile new file mode 100644 index 0000000000..7f2ddb4e58 --- /dev/null +++ b/package/system/wrt55agv2-spidevs/src/Makefile @@ -0,0 +1 @@ +obj-${CONFIG_WRT55AGV2_SPIDEVS} += wrt55agv2_spidevs.o
\ No newline at end of file diff --git a/package/system/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c b/package/system/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c new file mode 100644 index 0000000000..dfb7f6abe7 --- /dev/null +++ b/package/system/wrt55agv2-spidevs/src/wrt55agv2_spidevs.c @@ -0,0 +1,114 @@ +/* + * SPI driver for the Linksys WRT55AG v2 board. + * + * Copyright (C) 2008 Gabor Juhos <juhosg at openwrt.org> + * + * This file was based on the mmc_over_gpio driver: + * Copyright 2008 Michael Buesch <mb@bu3sch.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/platform_device.h> +#include <linux/spi/spi_gpio_old.h> +#include <linux/module.h> + +#define DRV_NAME "wrt55agv2-spidevs" +#define DRV_DESC "SPI driver for the WRT55AG v2 board" +#define DRV_VERSION "0.1.0" +#define PFX DRV_NAME ": " + +#define GPIO_PIN_MISO 1 +#define GPIO_PIN_CS 2 +#define GPIO_PIN_CLK 3 +#define GPIO_PIN_MOSI 4 + +static struct platform_device *spi_gpio_dev; + +static int __init boardinfo_setup(struct spi_board_info *bi, + struct spi_master *master, void *data) +{ + + strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); + + bi->max_speed_hz = 5000000 /* Hz */; + bi->bus_num = master->bus_num; + bi->mode = SPI_MODE_0; + + return 0; +} + +static int __init wrt55agv2_spidevs_init(void) +{ + struct spi_gpio_platform_data pdata; + int err; + + spi_gpio_dev = platform_device_alloc("spi-gpio", 0); + if (!spi_gpio_dev) { + printk(KERN_ERR PFX "no memory for spi-gpio device\n"); + return -ENOMEM; + } + + memset(&pdata, 0, sizeof(pdata)); + pdata.pin_miso = GPIO_PIN_MISO; + pdata.pin_cs = GPIO_PIN_CS; + pdata.pin_clk = GPIO_PIN_CLK; + pdata.pin_mosi = GPIO_PIN_MOSI; + pdata.cs_activelow = 1; + pdata.no_spi_delay = 1; + pdata.boardinfo_setup = boardinfo_setup; + pdata.boardinfo_setup_data = NULL; + + err = platform_device_add_data(spi_gpio_dev, &pdata, sizeof(pdata)); + if (err) + goto err_free_dev; + + err = platform_device_register(spi_gpio_dev); + if (err) { + printk(KERN_ERR PFX "unable to register device\n"); + goto err_free_pdata; + } + + return 0; + +err_free_pdata: + kfree(spi_gpio_dev->dev.platform_data); + spi_gpio_dev->dev.platform_data = NULL; + +err_free_dev: + platform_device_put(spi_gpio_dev); + return err; +} + +static void __exit wrt55agv2_spidevs_cleanup(void) +{ + if (!spi_gpio_dev) + return; + + platform_device_unregister(spi_gpio_dev); + + kfree(spi_gpio_dev->dev.platform_data); + spi_gpio_dev->dev.platform_data = NULL; + platform_device_put(spi_gpio_dev); +} + +static int __init wrt55agv2_spidevs_modinit(void) +{ + printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); + return wrt55agv2_spidevs_init(); +} +module_init(wrt55agv2_spidevs_modinit); + +static void __exit wrt55agv2_spidevs_modexit(void) +{ + wrt55agv2_spidevs_cleanup(); +} +module_exit(wrt55agv2_spidevs_modexit); + +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); +MODULE_LICENSE("GPL v2"); + |