From: blogic Date: Thu, 7 Jul 2011 19:56:31 +0000 (+0000) Subject: adds lantiq packages/drivers X-Git-Url: https://git.archive.openwrt.org/?a=commitdiff_plain;h=1c68520f6367a546871ce09075fe18abf42d0b0c;p=10.03%2Fopenwrt.git adds lantiq packages/drivers git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@27547 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/package/ltq-dsl-app/Makefile b/package/ltq-dsl-app/Makefile new file mode 100644 index 000000000..1b1aa369c --- /dev/null +++ b/package/ltq-dsl-app/Makefile @@ -0,0 +1,80 @@ +# +# 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_BASE_NAME:=dsl_cpe_control_danube +PKG_VERSION:=3.24.4.4 +PKG_RELEASE:=1 +PKG_SOURCE:=$(PKG_BASE_NAME)-$(PKG_VERSION).tar.gz +PKG_BUILD_DIR:=$(BUILD_DIR)/dsl_cpe_control-$(PKG_VERSION) +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ +PKG_MD5SUM:=ee315306626b68794d3d3636dabfe161 + +include $(INCLUDE_DIR)/package.mk + +define Package/ltq-dsl-app + SECTION:=net + CATEGORY:=Network + TITLE:=Lantiq DSL userland tool + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_lantiq_danube +kmod-ltq-dsl +libpthread + MAINTAINER:=John Crispin +endef + +define Package/ltq-dsl-app/description + Infineon DSL CPE API for Amazon SE, Danube and Vinax. +endef + +IFX_DSL_MAX_DEVICE=1 +IFX_DSL_LINES_PER_DEVICE=1 +IFX_DSL_CHANNELS_PER_LINE=1 +#CONFIG_IFX_CLI=y + +CONFIGURE_ARGS += \ + --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)" \ + --enable-danube \ + --enable-driver-include="-I$(STAGING_DIR)/usr/include" \ + --enable-debug-prints \ + --enable-add-appl-cflags="-DMAX_CLI_PIPES=2" \ + --enable-cmv-scripts \ + --enable-debug-tool-interface \ + --enable-adsl-led \ + --enable-dsl-ceoc \ + --enable-script-notification \ + --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 + +ifeq ($(CONFIG_IFX_CLI),y) +CONFIGURE_ARGS += \ + --enable-cli-support \ + --enable-soap-support +endif + +TARGET_CFLAGS += -I$(LINUX_DIR)/include + +define Package/ltq-dsl-app/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/ifx_cpe_control_init.sh $(1)/etc/init.d/ + + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/dsl_cpe_control $(1)/sbin +endef + +$(eval $(call BuildPackage,ltq-dsl-app)) diff --git a/package/ltq-dsl-app/files/ifx_cpe_control_init.sh b/package/ltq-dsl-app/files/ifx_cpe_control_init.sh new file mode 100644 index 000000000..91316938c --- /dev/null +++ b/package/ltq-dsl-app/files/ifx_cpe_control_init.sh @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2008 OpenWrt.org +START=99 + +start() { + + # start CPE dsl daemon in the background + /sbin/dsl_cpe_control -i -f /lib/firmware/ModemHWE.bin & + +# PS=`ps` +# echo $PS | grep -q dsl_cpe_control && { +# # workaround for nfs: allow write to pipes for non-root +# while [ ! -e /tmp/pipe/dsl_cpe1_ack ] ; do sleep 1; done +# chmod a+w /tmp/pipe/dsl_* +# } + echo $PS | grep -q dsl_cpe_control || { + echo "Start of dsl_cpe_control failed!!!" + false + } + +} diff --git a/package/ltq-dsl/Config.in b/package/ltq-dsl/Config.in new file mode 100644 index 000000000..6d9caf441 --- /dev/null +++ b/package/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/ltq-dsl/Makefile b/package/ltq-dsl/Makefile new file mode 100644 index 000000000..d645af777 --- /dev/null +++ b/package/ltq-dsl/Makefile @@ -0,0 +1,170 @@ +# +# 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:=2 +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 + +FW_BASE_NAME:=dsl_danube_firmware_adsl +FW_A_VER:=02.04.04.00.00.01 +FW_B_VER:=02.04.01.07.00.02 +FW_A_FILE_VER:=244001 +FW_B_FILE_VER:=241702 +FW_A_MD5:=f717db3067a0049a26e233ab11238710 +FW_B_MD5:=349de7cd20368f4ac9b7e8322114a512 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-dsl + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Lantiq dsl driver + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_lantiq_danube +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) + MAINTAINER:=John Crispin +endef + +define Package/kmod-ltq-dsl-firmware/default + SECTION:=sys + CATEGORY:=Kernel modules + SUBMENU:=Network Devices + TITLE:=Firmware + URL:=http://www.lantiq.com/ + DEPENDS:=@TARGET_lantiq_danube kmod-ltq-dsl + MAINTAINER:=John Crispin +endef + +define Package/kmod-ltq-dsl-firmware-a + $(call Package/kmod-ltq-dsl-firmware/default) + TITLE+=Annex-A Danube +endef + +define Package/kmod-ltq-dsl-firmware-b + $(call Package/kmod-ltq-dsl-firmware/default) + TITLE+=Annex-B Danube +endef + +define KernelPackage/ltq-dsl/description + Lantiq DSL CPE API for Amazon SE, Danube and Vinax. +endef + +define KernelPackage/ltq-dsl/config + source "$(SOURCE)/Config.in" +endef + +define Download/annex-a + FILE:=$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz + URL:=http://mirror2.openwrt.org/sources/ + MD5SUM:=$(FW_A_MD5) +endef +$(eval $(call Download,annex-a)) + +define Download/annex-b + FILE:=$(FW_BASE_NAME)_b-$(FW_B_VER).tar.gz + URL:=http://mirror2.openwrt.org/sources/ + MD5SUM:=$(FW_B_MD5) +endef +$(eval $(call Download,annex-b)) + +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)" \ + --enable-danube \ + --enable-add-drv-cflags="-DMODULE" \ + --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) + +EXTRA_CFLAGS = -fno-pic -mno-abicalls -mlong-calls -G 0 + +ifeq ($(CONFIG_LANTIQ_DSL_DEBUG),y) +CONFIGURE_ARGS += \ + --enable-debug=yes \ + --enable-debug-prints=yes +EXTRA_CFLAGS += -DDEBUG +endif + +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) -xzf $(DL_DIR)/$(FW_BASE_NAME)_a-$(FW_A_VER).tar.gz + $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(FW_BASE_NAME)_b-$(FW_B_VER).tar.gz +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) 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-a/install + $(INSTALL_DIR) $(1)/lib/firmware/ + $(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_a_$(FW_A_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin +endef + +define Package/kmod-ltq-dsl-firmware-b/install + $(INSTALL_DIR) $(1)/lib/firmware/ + $(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_b_$(FW_B_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin +endef + +$(eval $(call KernelPackage,ltq-dsl)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-a)) +$(eval $(call BuildPackage,kmod-ltq-dsl-firmware-b)) diff --git a/package/ltq-dsl/patches/100-dsl_compat.patch b/package/ltq-dsl/patches/100-dsl_compat.patch new file mode 100644 index 000000000..f892351a6 --- /dev/null +++ b/package/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 + + #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 +-#include ++#include + #include + #include + #include + #include + #include + #include +- ++#include + + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +- #include ++ #include + #endif + + #include diff --git a/package/ltq-dsl/patches/500-portability.patch b/package/ltq-dsl/patches/500-portability.patch new file mode 100644 index 000000000..d74314c77 --- /dev/null +++ b/package/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 +-#include + #include + #include + #include +@@ -26,8 +24,10 @@ + #include + #include + +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +- #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++#include ++#else ++#include + #endif + + #include +@@ -39,7 +39,8 @@ + #include + #include + #include +-#include ++//#include ++#include + + #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT + /** IFXOS includes*/ diff --git a/package/ltq-dsl/src/Makefile b/package/ltq-dsl/src/Makefile new file mode 100644 index 000000000..89c4e712d --- /dev/null +++ b/package/ltq-dsl/src/Makefile @@ -0,0 +1,3 @@ +obj-m = lantiq_mei.o lantiq_atm.o + +lantiq_atm-objs := ifxmips_atm_core.o ifxmips_atm_danube.o diff --git a/package/ltq-dsl/src/ifx_atm.h b/package/ltq-dsl/src/ifx_atm.h new file mode 100644 index 000000000..32deca54e --- /dev/null +++ b/package/ltq-dsl/src/ifx_atm.h @@ -0,0 +1,108 @@ +/****************************************************************************** +** +** 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 + + + +/* + * 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; + +/*! + \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 + +/*@}*/ + + + +#ifdef __KERNEL__ +struct port_cell_info { + unsigned int port_num; + unsigned int tx_link_rate[2]; +}; +#endif +#endif diff --git a/package/ltq-dsl/src/ifxmips_atm.h b/package/ltq-dsl/src/ifxmips_atm.h new file mode 100644 index 000000000..ed90b5d4d --- /dev/null +++ b/package/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/ltq-dsl/src/ifxmips_atm_core.c b/package/ltq-dsl/src/ifxmips_atm_core.c new file mode 100644 index 000000000..49a31fc59 --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_core.c @@ -0,0 +1,2513 @@ +/****************************************************************************** +** +** 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 8 + + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Chip Specific Head File + */ +#include +#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 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 int 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 *); + +/* + * Debug Functions + */ +#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB + static void dump_skb(struct sk_buff *, u32, char *, int, int, int); +#else + #define dump_skb(skb, len, title, port, ch, is_tx) 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_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 *); +#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 *); +#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); +#endif +static INLINE int ifx_atm_version(char *); +//static INLINE int print_reset_domain(char *, int); +//static INLINE int print_reset_handler(char *, int, ifx_rcu_handler_t *); + +/* + * Init & clean-up functions + */ +#ifdef MODULE + static INLINE void reset_ppe(void); +#endif +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) + extern int ifx_mei_atm_led_blink(void); + extern int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr); +#else + static inline int ifx_mei_atm_led_blink(void) { return IFX_SUCCESS; } + 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 + */ +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 *); + extern int (*ifx_mei_atm_showtime_exit)(void); +#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; + +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; + + /* 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)) + || (vcc->qos.txtp.traffic_class == ATM_VBR_RT && vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + || (vcc->qos.txtp.traffic_class == ATM_VBR_NRT && vcc->qos.txtp.scr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) + || (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS && vcc->qos.txtp.min_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) ) + { + ret = -EINVAL; + goto PPE_OPEN_EXIT; + } + + /* 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 ) + { + 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)->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 ( 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); + + /* release connection */ + clear_bit(conn, &g_atm_priv_data.conn_table); + connection->vcc = NULL; + connection->aal5_vcc_crc_err = 0; + connection->aal5_vcc_oversize_sdu = 0; + + /* 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_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 */ + g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc; + dma_cache_wback((unsigned long)skb->data, skb->len); + + 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); + + 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 int adsl_led_flash(void) +{ + return ifx_mei_atm_led_blink(); +} + +/* + * 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) +{ + if ( is_tx ) { + while ( MBOX_IGU3_ISR_ISR(queue + FIRST_QSB_QID + 16) ); + *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue + FIRST_QSB_QID + 16); + } + else { + while ( MBOX_IGU3_ISR_ISR(queue) ); + *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue); + } +} + +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(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB +static void dump_skb(struct sk_buff *skb, u32 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", (u32)skb, (u32)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", (u32)skb->data, (u32)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 + +static INLINE void proc_file_create(void) +{ +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + struct proc_dir_entry *res; +#endif + + 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_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; + } +#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); +#endif +} + +static INLINE void proc_file_delete(void) +{ +#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC + remove_proc_entry("txq", g_atm_dir); + + remove_proc_entry("htu", g_atm_dir); +#endif + +#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC + remove_proc_entry("dbg", g_atm_dir); +#endif + + 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[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, "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_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"); + + *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", + " all" + }; + static const int dbg_enable_mask_str_len[] = { + 12, 4, + 12, 4, + 7, 7, + 12, 3, + 12, 3, + 9, 4, + 10, 5, + 4 + }; + u32 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_ALL + }; + + char str[2048]; + char *p; + + int len, rlen; + + int f_enable = 0; + 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 ( 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 [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; + else + ifx_atm_dbg_enable &= ~DBG_ENABLE_MASK_ALL; + } + 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) ); + } + } + + return count; +} + +#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", *(u32*)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", *(u32*)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", *(u32*)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; + char str[1024]; + int llen; + + int htuts = *CFG_WRX_HTUTS; + int i; + + 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; + + 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 %s\n", *(u32*)WTX_QUEUE_CONFIG(i), (unsigned int)WTX_QUEUE_CONFIG(i)->sbid, WTX_QUEUE_CONFIG(i)->qsben ? "enable" : "disable"); + len += sprintf(buf + len, " dma 0x%08x - base %08x, len %u, vlddes %u\n", *(u32*)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; + char str[1024]; + int llen; + + int i; + + 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; + + return len - off; + +PROC_READ_HTU_OVERRUN_END: + + return len - llen - off; +} + +#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; +} +#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, "Infineon Technologies ATM driver version %d.%d.%d\n", IFX_ATM_VER_MAJOR, IFX_ATM_VER_MID, IFX_ATM_VER_MINOR); + len += sprintf(buf + len, "Infineon Technologies ATM (A1) firmware version %d.%d\n", major, minor); + + return len; +} + +#ifdef MODULE +static INLINE void reset_ppe(void) +{ + // TODO: +} +#endif + +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; + *CFG_WRX_QNUM = MAX_QUEUE_NUMBER; + *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.type = 0x0; + wtx_queue_config.qsben = 1; + wtx_queue_config.sbid = 0; + for ( i = 0; i < MAX_TX_DMA_CHANNEL_NUMBER; 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 + + pr_debug("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 defined(CONFIG_VR9) + IFX_REG_W32(0x00, UTP_CFG); +#endif + + g_showtime = 0; + + // TODO: ReTX clean state + g_xdata_addr = NULL; + + pr_debug("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]; + +#ifdef MODULE + reset_ppe(); +#endif + + 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); + + ret = ifx_pp32_start(0); + if ( ret ) { + err("ifx_pp32_start fail!"); + goto PP32_START_FAIL; + } + + port_cell.port_num = ATM_PORT_NUMBER; + 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(); + + /* create proc file */ + proc_file_create(); + + ifx_mei_atm_showtime_enter = atm_showtime_enter; + 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; + + ifx_mei_atm_showtime_enter = NULL; + ifx_mei_atm_showtime_exit = NULL; + + proc_file_delete(); + + invalidate_oam_htu_entry(); + + ifx_pp32_stop(0); + + 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/ltq-dsl/src/ifxmips_atm_core.h b/package/ltq-dsl/src/ifxmips_atm_core.h new file mode 100644 index 000000000..8f0a3ebfb --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_core.h @@ -0,0 +1,249 @@ +/****************************************************************************** +** +** 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 ENABLE_DBG_PROC 1 + +#define ENABLE_FW_PROC 1 + +#ifdef CONFIG_IFX_ATM_TASKLET + #define ENABLE_TASKLET 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_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) + +#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 + + + +/* + * #################################### + * 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); + + + +#endif // IFXMIPS_ATM_CORE_H diff --git a/package/ltq-dsl/src/ifxmips_atm_danube.c b/package/ltq-dsl/src/ifxmips_atm_danube.c new file mode 100644 index 000000000..583b5646b --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_danube.c @@ -0,0 +1,270 @@ +/****************************************************************************** +** +** 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Chip Specific Head File + */ +#include +#include "ifxmips_compat.h" +#include "ifxmips_atm_core.h" +#include "ifxmips_atm_fw_danube.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 (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 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); +} + +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 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) +{ + // for ReTX expansion in future + //*FFSM_CFG0 = SET_BITS(*FFSM_CFG0, 5, 0, 6); // pnum = 6 + //*FFSM_CFG1 = SET_BITS(*FFSM_CFG1, 5, 0, 6); // pnum = 6 +} + +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(0x02, 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"); + + *major = ATM_FW_VER_MAJOR; + *minor = ATM_FW_VER_MINOR; +} + +void ifx_atm_init_chip(void) +{ + init_pmu(); + + 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/ltq-dsl/src/ifxmips_atm_fw_danube.h b/package/ltq-dsl/src/ifxmips_atm_fw_danube.h new file mode 100644 index 000000000..c36c96845 --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_fw_danube.h @@ -0,0 +1,429 @@ +#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 ATM_FW_VER_MAJOR 0 +#define ATM_FW_VER_MINOR 1 + + +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, 0x80004710, 0xC2000000, 0xDA080001, 0x80003D98, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003D50, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80004F18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x80003C50, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC0400000, 0xC0004840, 0xC8840000, 0x800043D0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xC0400002, 0xC0004840, 0xC8840000, 0x80004350, 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, 0x80004380, 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, 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, + 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, 0x99005930, 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, 0x990060A8, 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, 0x99005370, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC0004934, 0xCA400000, 0xC2000000, + 0xC2800002, 0x990053B0, 0xDA980000, 0xC6140000, 0xC6580000, 0xC161FFFE, 0x5955FFFE, 0x15400000, + 0x00000000, 0x99005498, 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, 0x99005708, 0xC000491C, 0xC1400000, 0xC9420050, 0x00000000, + 0x00000000, 0x00000000, 0xA8E2FFC8, 0xC2000000, 0xC1220002, 0xD90C0000, 0xDF600040, 0x5E600080, + 0x8400FFDA, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, 0x00000000, 0x99005930, + 0xDA180000, 0xDA580001, 0x00000000, 0xC2000000, 0xDF610050, 0x5E6001FE, 0x8800FFD0, 0xC0004916, + 0xCA800000, 0xC2C00000, 0xDFEC0050, 0xC2400000, 0x46E52000, 0x84000032, 0x5EA80000, 0x84000022, + 0xC2600002, 0x990060A8, 0xC000482E, 0xC9400000, 0xC1800002, 0x80000018, 0xC2600000, 0x990060A8, + 0xC000482C, 0xC9400000, 0xC1800002, 0xC2000068, 0xC6240080, 0xC0004930, 0xCE400088, 0xC000491A, + 0xC9800000, 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99005790, 0xD9580000, + 0xD9980001, 0xD9D40000, 0x99005708, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xDF600040, + 0x5E600080, 0x8400FFD2, 0x00000000, 0xC000491C, 0xCA000000, 0xC000491E, 0xCA400000, 0x00000000, + 0x00000000, 0x99005930, 0xDA180000, 0xDA580001, 0x00000000, 0x800010D0, 0x00000000, 0x990060A8, + 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, 0x99005498, 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, 0x99005370, 0xC1A0FFFE, 0xC0000824, 0xC9840068, 0xC2000000, 0xC0004930, + 0xCA02E010, 0x58380026, 0xCA400000, 0x00000000, 0xC2800000, 0x990053B0, 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, 0x990060A8, + 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, 0x990060A8, 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, 0x99005708, 0xC000491C, 0xC1400000, 0xC9420050, 0x80000020, + 0x00000000, 0x990060A8, 0xC0004826, 0xC9400000, 0xC1800002, 0x8000FDC0, 0xC2000000, 0xC2400200, + 0xDF600040, 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005930, 0xDA580000, + 0xDA980001, 0x00000000, 0xC0004934, 0xCA000000, 0x00000000, 0xC2800000, 0xA6020140, 0xC2400004, + 0xC2000200, 0xDF690050, 0x46A14000, 0x46694000, 0x8800FFC2, 0x00000000, 0xC000491A, 0xC9800000, + 0xC0004862, 0xC9400000, 0x6D9C6000, 0x459CE000, 0x59DC4C80, 0x99005790, 0xD9580000, 0xD9980001, + 0xD9D40000, 0x99005708, 0xC000491C, 0xC1400000, 0xC9420050, 0xC2000000, 0xC2400200, 0xDF600040, + 0xB624FFCA, 0xC000491C, 0xCA400000, 0xC000491E, 0xCA800000, 0x99005930, 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, + 0x99005930, 0xDB980000, 0xDBD80001, 0x00000000, 0xC2000000, 0xDF600040, 0x5E200080, 0x8400028A, + 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC000490E, 0xCA000000, 0xC000492A, + 0xCA400000, 0xC000496A, 0xCB000000, 0xC0004956, 0xCAC00000, 0x00000000, 0xC121FFFE, 0x5911FE14, + 0x15000000, 0x76318000, 0x76718000, 0x840001EA, 0xC201FFFE, 0x76318000, 0x5AEC0002, 0x6B2D0010, + 0x5EA00000, 0x84000002, 0x6A2D0000, 0x8000FFF8, 0xC7200000, 0x62016008, 0xC0004956, 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, 0x99005930, + 0xDB980000, 0xDBD80001, 0x00000000, 0xC000495A, 0xC8400000, 0x00000000, 0xC3C00002, 0x7BC42000, + 0xCC400000, 0xC0001A1C, 0xCA000000, 0xC2400008, 0x6A452000, 0x76610000, 0x8400D91A, 0xC0000A28, + 0xC3800000, 0xCB840030, 0xC0000A14, 0xC3400000, 0xCB440030, 0xC0004880, 0xCB040000, 0xB7B4D8CA, + 0x58041802, 0xCAC00000, 0xA7000018, 0x00000000, 0x00000000, 0xA6C8D898, 0xC2800000, 0xC6E80020, + 0x80000030, 0xC2800000, 0xC7282020, 0xC000490E, 0xCA400000, 0x6BE9E000, 0x00000000, 0x77E52000, + 0x8400D848, 0x6EA0A000, 0x6E944000, 0x45610000, 0x46A10000, 0x5A204E20, 0x5820000C, 0xCA000000, + 0xC0004946, 0xCE800000, 0xA6220348, 0x00000000, 0xC2200060, 0xC0004948, 0xCE000010, 0xCE001040, + 0xC240000A, 0xC000494A, 0xCE400000, 0xC2B60002, 0xC0004964, 0xCE801B08, 0x99005C00, 0xC00048A0, + 0xC8840000, 0x00000000, 0xC0004946, 0xCBC00000, 0x00000000, 0x00000000, 0x6FF8A000, 0x6FD44000, + 0x4579C000, 0x47F9C000, 0x5BB84E20, 0x990059C0, 0xDBD80000, 0xDB980001, 0x00000000, 0x99005708, + 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C, 0x99005BB8, 0xC9400001, 0xC9800000, 0x00000000, + 0x99005930, 0xD9580000, 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, + 0x990055F8, 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, + 0x990060A8, 0xC0004836, 0xC9400000, 0xC1800002, 0x00000000, 0x00000000, 0x00000000, 0xA8E2FFC8, + 0x00000000, 0xC1220002, 0xD90C0000, 0xC2000000, 0xC0000A14, 0xCA040030, 0xC0000A28, 0xC2500002, + 0xCE440808, 0x58880002, 0xB608FFF8, 0xC00048A0, 0xC0800000, 0xCC840000, 0x8000D498, 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, 0x99005D40, 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, 0x99005D40, 0xDBD80000, 0xDB980001, 0xC7800000, 0x99005F40, 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, 0x99005C00, 0xC00048A0, 0xC8840000, 0x00000000, + 0xC0004946, 0xCBC00000, 0xC000494C, 0xCA000000, 0x6FF8A000, 0x6FD44000, 0x4579C000, 0x47F9C000, + 0x5BB84E20, 0x5E200000, 0x840000E2, 0x00000000, 0x990059C0, 0xDBD80000, 0xDB980001, 0x00000000, + 0x99005708, 0xC000491C, 0xC1400000, 0xC9420050, 0xC000491C, 0x99005BB8, 0xC9400001, 0xC9800000, + 0x00000000, 0x99005930, 0xD9580000, 0xD9980001, 0x00000000, 0xC161FFFE, 0x5955FFFE, 0x15400000, + 0x00000000, 0x990055F8, 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, 0x990060A8, 0xC0004834, 0xC9400000, 0xC1800002, 0x990060A8, 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, 0x8400013A, 0x5E200000, + 0x84000128, 0xC000493C, 0xCA800000, 0x00000000, 0x00000000, 0x5AA80060, 0xCE800000, 0x99005D40, + 0xDBD80000, 0xDB980001, 0xC7800000, 0x99005F40, 0xDBD80000, 0xDB980001, 0xC7800000, 0xC0004952, + 0xCAC00000, 0x58380000, 0xCA800000, 0xC30C0002, 0xC7F00020, 0xA6800078, 0x00000000, 0x00000000, + 0xC161FFFE, 0x5955FFFE, 0x15400000, 0x00000000, 0xC0001800, 0xCA000000, 0x00000000, 0x00000000, + 0xA60CFFCA, 0xC6F00508, 0xC6B0C408, 0xCF000000, 0x00000000, 0xC121FFFE, 0x5911FE14, 0x15000000, + 0x8000CB48, 0xDCBC0001, 0x5FFC0000, 0x8400003A, 0xC3800002, 0xDB880001, 0x5FFC0004, 0x8400C4B2, + 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, 0x99005348, 0xC0004848, 0xC9440000, + 0xC1800000, 0xC11C0002, 0xC000082C, 0xCD040E08, 0x800005C8, 0x5B740002, 0xC0004858, 0xCF440000, + 0xC7800000, 0xC13C0002, 0xCD001E08, 0xC0004848, 0xC9440000, 0xC1800000, 0xC000082C, 0xC9840030, + 0x59540002, 0xC0004848, 0xCD440000, 0x58880002, 0xB4980540, 0x00000000, 0xC0800000, 0x80000530, + 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, 0xB4980430, 0x00000000, + 0xC0800000, 0x80000420, 0xC0004854, 0xC1000004, 0xCD040000, 0xC0000820, 0xC2000002, 0xCE040000, + 0xC2000000, 0xC000484C, 0xCE040000, 0xC0004858, 0xCE040000, 0x8000FF10, 0xC0004854, 0xC1000000, + 0xCD040000, 0xC11C0000, 0xC000082C, 0xCD040E08, 0x99005348, 0xC0004848, 0xC9440000, 0xC1800000, + 0xC1200000, 0xC0000818, 0xCD041008, 0xC11C0002, 0xC000082C, 0xCD040E08, 0xC2000000, 0xC000484C, + 0xCE040000, 0x80000320, 0xC0001AC0, 0xCB840000, 0xC000487C, 0xC8040000, 0x00000000, 0x00000000, + 0x40080000, 0xCBC00000, 0xC4280000, 0x00000000, 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, 0x99005348, 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, 0x8000B908, 0xC0004840, 0xCC840000, 0x8000F6B8, + 0xC0001AC0, 0xCAC40000, 0xC0004854, 0xCB440000, 0xA6C0FBD2, 0x00000000, 0x5EF40000, 0x8400F712, + 0x5EF40002, 0x8400F9A2, 0x5EF40004, 0x8400FBA2, 0xC1006CE8, 0x8000B880, 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, 0x8400B6F0, 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, 0xC0001408, 0xCC800000, 0xC10E0002, 0xD90C0000, 0x8000EDA8, 0xDFBC0001, 0xC000496E, + 0x99006050, 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, 0x8000EB18, + 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, + 0xC1800100, 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/ltq-dsl/src/ifxmips_atm_fw_regs_common.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h new file mode 100644 index 000000000..a5f59b8c4 --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_common.h @@ -0,0 +1,364 @@ +#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 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 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 res2 :3; + unsigned int type :2; + unsigned int qsben :1; + }; + + 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 type :2; + unsigned int res2 :3; + 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) + + + +#endif // IFXMIPS_ATM_FW_REGS_COMMON_H diff --git a/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h b/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h new file mode 100644 index 000000000..c0dfc6a2e --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_fw_regs_danube.h @@ -0,0 +1,30 @@ +#ifndef IFXMIPS_ATM_FW_REGS_DANUBE_H +#define IFXMIPS_ATM_FW_REGS_DANUBE_H + + + +/* + * Host-PPE Communication Data Address Mapping + */ +#define 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_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(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)) +#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))) + + + +#endif // IFXMIPS_ATM_FW_REGS_DANUBE_H diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_common.h b/package/ltq-dsl/src/ifxmips_atm_ppe_common.h new file mode 100644 index 000000000..c922276df --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_ppe_common.h @@ -0,0 +1,231 @@ +#ifndef IFXMIPS_ATM_PPE_COMMON_H +#define IFXMIPS_ATM_PPE_COMMON_H + +#if defined(CONFIG_LANTIQ) + #include "ifxmips_atm_ppe_danube.h" + #define CONFIG_DANUBE +#elif 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 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) + + + +#endif // IFXMIPS_ATM_PPE_COMMON_H diff --git a/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h b/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h new file mode 100644 index 000000000..34cf87705 --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_atm_ppe_danube.h @@ -0,0 +1,100 @@ +#ifndef IFXMIPS_ATM_PPE_DANUBE_H +#define IFXMIPS_ATM_PPE_DANUBE_H + +#include + +/* + * 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) + +/* + * 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/ltq-dsl/src/ifxmips_compat.h b/package/ltq-dsl/src/ifxmips_compat.h new file mode 100644 index 000000000..ae375b7e6 --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_compat.h @@ -0,0 +1,43 @@ +#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_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) + +#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 + +#endif diff --git a/package/ltq-dsl/src/ifxmips_mei_interface.h b/package/ltq-dsl/src/ifxmips_mei_interface.h new file mode 100644 index 000000000..ffde6113c --- /dev/null +++ b/package/ltq-dsl/src/ifxmips_mei_interface.h @@ -0,0 +1,700 @@ +/****************************************************************************** + + 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_DANUBE 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/ltq-dsl/src/lantiq_mei.c b/package/ltq-dsl/src/lantiq_mei.c new file mode 100644 index 000000000..ac818929c --- /dev/null +++ b/package/ltq-dsl/src/lantiq_mei.c @@ -0,0 +1,3036 @@ +/****************************************************************************** + + 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 +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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 +#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 + disable_irq (IFXMIPS_USB_OC_INT0); + disable_irq (IFXMIPS_USB_OC_INT2); + #elif defined(CONFIG_LANTIQ_AR9) + 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_LANTIQ_AMAZON_S) + 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/ltq-ifxos/Makefile b/package/ltq-ifxos/Makefile new file mode 100644 index 000000000..87a5b63ac --- /dev/null +++ b/package/ltq-ifxos/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (C) 2009-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:=lib_ifxos +PKG_VERSION:=1.5.14 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_RELEASE:=3 +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=ba775356bdd5e1b73b3e11a152710ed6 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-ifxos + SUBMENU:=Voice over IP + TITLE:=Lantiq OS abstraction library + URL:=http://www.lantiq.com/ + MAINTAINER:=Lantiq + DEPENDS:=@TARGET_lantiq @!TARGET_lantiq_ase + FILES:=$(PKG_BUILD_DIR)/src/drv_ifxos.ko + AUTOLOAD:=$(call AutoLoad,10,drv_ifxos) +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-add_drv_cflags="-fno-pic -mno-abicalls -mlong-calls -G 0" + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +ifdef CONFIG_TARGET_lantiq + define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/{lib,include/ifxos} + $(CP) $(PKG_BUILD_DIR)/src/include/* $(1)/usr/include/ifxos + mkdir -p $(1)/usr/lib + $(CP) $(PKG_BUILD_DIR)/src/libifxos.a $(1)/usr/lib/libifxos.a + endef +endif + +$(eval $(call KernelPackage,ltq-ifxos)) diff --git a/package/ltq-ifxos/patches/100-portability.patch b/package/ltq-ifxos/patches/100-portability.patch new file mode 100644 index 000000000..d1ce7503a --- /dev/null +++ b/package/ltq-ifxos/patches/100-portability.patch @@ -0,0 +1,11 @@ +--- a/configure.in ++++ b/configure.in +@@ -64,7 +64,7 @@ dnl Set kernel build path + AC_ARG_ENABLE(kernelbuild, + AS_HELP_STRING(--enable-kernelbuild=x,Set the target kernel build path (only for kernel 2.6.x)), + [ +- 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!]) diff --git a/package/ltq-ifxos/patches/120-fix_smp_lock.patch b/package/ltq-ifxos/patches/120-fix_smp_lock.patch new file mode 100644 index 000000000..aea4305a9 --- /dev/null +++ b/package/ltq-ifxos/patches/120-fix_smp_lock.patch @@ -0,0 +1,12 @@ +--- a/src/linux/ifxos_linux_thread_drv.c ++++ b/src/linux/ifxos_linux_thread_drv.c +@@ -34,7 +34,9 @@ + #include + #include + #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include ++#endif + #include + + diff --git a/package/ltq-kpi2udp/Makefile b/package/ltq-kpi2udp/Makefile new file mode 100644 index 000000000..497f743e0 --- /dev/null +++ b/package/ltq-kpi2udp/Makefile @@ -0,0 +1,48 @@ +# +# 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:=drv_kpi2udp +PKG_VERSION:=2.2.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=drv_kpi2udp-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=af3855609554c7f3d2c3df8c597f50a7 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-kpi2udp + SUBMENU:=Voice over IP + TITLE:=TAPI KPI2UDP plug-in + URL:=http://www.lantiq.com/ + DEPENDS:=+kmod-ltq-tapi @TARGET_lantiq + FILES:=$(PKG_BUILD_DIR)/drv_kpi2udp.ko + AUTOLOAD:=$(call AutoLoad,26,drv_kpi2udp) + MAINTAINER:=John Crispin +endef + +define KernelPackage/ltq-kpi2udp/description + RTP packet path accelleration into IP stack (strongly recommended) +endef + +CONFIGURE_ARGS += --enable-kernelincl="$(LINUX_DIR)/include" \ + --enable-tapiincl="$(STAGING_DIR)/usr/include/drv_tapi" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + --enable-warning \ + --enable-linux-26 \ + --enable-kernelbuild="$(LINUX_DIR)" \ + ARCH=$(LINUX_KARCH) + +define Build/Configure + (cd $(PKG_BUILD_DIR); aclocal && autoconf && automake) + $(call Build/Configure/Default) +endef + +$(eval $(call KernelPackage,ltq-kpi2udp)) diff --git a/package/ltq-kpi2udp/patches/100-owner.patch b/package/ltq-kpi2udp/patches/100-owner.patch new file mode 100644 index 000000000..8afe535a8 --- /dev/null +++ b/package/ltq-kpi2udp/patches/100-owner.patch @@ -0,0 +1,11 @@ +--- a/ifx_udp_redirect.c ++++ b/ifx_udp_redirect.c +@@ -256,7 +256,7 @@ + { + if (redtab.channels[i].in_use == IFX_TRUE) + { +- if (redtab.channels[i].sk->sk_lock.owner != 0) ++ if (redtab.channels[i].sk->sk_lock.owned != 0) + return IFX_TRUE; + } + } diff --git a/package/ltq-tapi/Config.in b/package/ltq-tapi/Config.in new file mode 100644 index 000000000..84dbef239 --- /dev/null +++ b/package/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/ltq-tapi/Makefile b/package/ltq-tapi/Makefile new file mode 100644 index 000000000..29c6f5e4a --- /dev/null +++ b/package/ltq-tapi/Makefile @@ -0,0 +1,69 @@ +# +# 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 + +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/ltq-tapi + SUBMENU:=Voice over IP + TITLE:=Lantiq TAPI subsystem + URL:=http://www.lantiq.com/ + DEPENDS:=+kmod-ltq-ifxos @TARGET_lantiq @!TARGET_lantiq_ase + FILES:=$(PKG_BUILD_DIR)/src/drv_tapi.ko + AUTOLOAD:=$(call AutoLoad,20,drv_tapi) + MAINTAINER:=John Crispin +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/ltq-tapi/patches/000-portability.patch b/package/ltq-tapi/patches/000-portability.patch new file mode 100644 index 000000000..78fcbad66 --- /dev/null +++ b/package/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 + #include /* in_interrupt() */ + #include /* mdelay - udelay */ ++#include /* work_struct */ + #include /* 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 + #include /* copy_from_user(), ... */ + #include ++#include /* lock_kernel() */ + #include + + #ifdef LINUX_2_6 +@@ -55,7 +56,11 @@ + #include + #undef CONFIG_DEVFS_FS + #ifndef UTS_RELEASE +- #include "linux/utsrelease.h" ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++# include ++#else ++# include ++#endif + #endif /* UTC_RELEASE */ + #else + #include +@@ -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/ltq-tapi/patches/100-ifxmips.patch b/package/ltq-tapi/patches/100-ifxmips.patch new file mode 100644 index 000000000..a9c0d8116 --- /dev/null +++ b/package/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 + #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/ltq-tapi/patches/200-linux-37.patch b/package/ltq-tapi/patches/200-linux-37.patch new file mode 100644 index 000000000..9d7428df0 --- /dev/null +++ b/package/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 + #include /* copy_from_user(), ... */ + #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include /* lock_kernel() */ ++#endif + #include + + #ifdef LINUX_2_6 +@@ -65,7 +67,9 @@ + #else + #include + #include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include /* 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 +-#elif VXWORKS ++#elif defined(VXWORKS) + #include + #endif /* LINUX */ + diff --git a/package/ltq-tapidemo/Config.in b/package/ltq-tapidemo/Config.in new file mode 100644 index 000000000..a799eddd0 --- /dev/null +++ b/package/ltq-tapidemo/Config.in @@ -0,0 +1,47 @@ +choice + prompt "board selection" + depends on PACKAGE_ltq-tapidemo + default VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 if TARGET_lantiq_danube + default VOICE_CPE_TAPIDEMO_BOARD_EASY508xx if TARGET_lantiq_ar9 + default VOICE_CPE_TAPIDEMO_BOARD_EASY80910 if TARGET_lantiq_vr9 + help + Select the target platform. + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712 + bool "Danube reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3 + bool "Danube reference board V3" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY508xx + bool "AR9/GR9 reference board" + + config VOICE_CPE_TAPIDEMO_BOARD_EASY80910 + bool "VR9 reference board" +endchoice + +config VOICE_CPE_TAPIDEMO_QOS + bool "enable QOS support" + depends on PACKAGE_ltq-tapidemo + select PACKAGE_kmod-ltq-kpi2udp + default y + help + Option to enable the KPI2UDP RTP packet acceleration path + (highly recommended for VoIP). + +config VOICE_CPE_TAPIDEMO_FAX_T.38_FW + bool "enable T.38 fax relay" + depends on (TARGET_lantiq_ar9 || TARGET_lantiq_vr9) && PACKAGE_ltq-tapidemo + default n + help + enable T.38 fax relay demo. + +config VOICE_CPE_TAPIDEMO_FW_FILE + string "override default firmware file" + depends on PACKAGE_ltq-tapidemo + default "falcon_voip_fw.bin" if TARGET_lantiq_falcon + +config VOICE_CPE_TAPIDEMO_BBD_FILE + string "override default coefficient file" + depends on PACKAGE_ltq-tapidemo + default "falcon_bbd.bin" if TARGET_lantiq_falcon diff --git a/package/ltq-tapidemo/Makefile b/package/ltq-tapidemo/Makefile new file mode 100644 index 000000000..14c93ef7d --- /dev/null +++ b/package/ltq-tapidemo/Makefile @@ -0,0 +1,79 @@ +# +# 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:=tapidemo +PKG_VERSION:=5.1.0.53 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources +PKG_MD5SUM:=c970becc46b2935fb9e18f795d4e8469 + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/ltq-tapidemo + SUBMENU:=Telephony + SECTION:=net + CATEGORY:=Network + TITLE:=TAPIdemo application for Lantiq boards + URL:=http://www.lantiq.com/ + DEPENDS:=+kmod-ltq-tapi +kmod-ltq-vmmc + MAINTAINER:=John Crispin + MENU:=1 +endef + +define Package/ltq-tapidemo/description + Voice Access mini-PBX Demo Application +endef + +define Package/ltq-tapidemo/config + source "$(SOURCE)/Config.in" +endef + +CONFIGURE_ARGS += \ + ARCH=$(LINUX_KARCH) \ + --enable-linux-26 \ + --enable-kernelincl="$(LINUX_DIR)/include" \ + --with-drvincl="$(STAGING_DIR)/usr/include" \ + --with-ifxos-incl=$(STAGING_DIR)/usr/include/ifxos \ + --with-ifxos-lib=$(STAGING_DIR)/usr/lib \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPI_QOS,qos) \ + $(call autoconf_bool,CONFIG_VOICE_CPE_TAPIDEMO_FAX_T,fax-t38) \ + --enable-trace \ + --enable-fs + +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY50712_V3),y) + CONFIGURE_ARGS += --enable-boardname=EASY50712_V3 +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY508xx),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif +ifeq ($(CONFIG_VOICE_CPE_TAPIDEMO_BOARD_EASY80910),y) + CONFIGURE_ARGS += --enable-boardname=EASY508XX +endif +ifneq ($(CONFIG_VOICE_CPE_TAPIDEMO_FW_FILE),) + CONFIGURE_ARGS += --with-fw-file="$(strip $(subst ",, $(CONFIG_VOICE_CPE_TAPIDEMO_FW_FILE)))" +endif +ifneq ($(CONFIG_VOICE_CPE_TAPIDEMO_BBD_FILE), "") +CONFIGURE_ARGS += --with-bbd-file="$(strip $(subst ",, $(CONFIG_VOICE_CPE_TAPIDEMO_BBD_FILE)))" +endif + +define Package/ltq-tapidemo/install + $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tapidemo $(1)/usr/sbin + $(INSTALL_BIN) ./files/bringup_tapidemo $(1)/etc/init.d/tapidemo +endef + +$(eval $(call BuildPackage,ltq-tapidemo)) diff --git a/package/ltq-tapidemo/files/bringup_tapidemo b/package/ltq-tapidemo/files/bringup_tapidemo new file mode 100644 index 000000000..6eb13d25f --- /dev/null +++ b/package/ltq-tapidemo/files/bringup_tapidemo @@ -0,0 +1,89 @@ +#!/bin/sh /etc/rc.common +# (C) 2008 openwrt.org + +START=96 + +[ ! -f /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 +} + +TD_EXTRA_FLAGS_FXO= +TD_EXTRA_FLAGS_KPI2UDP= +TD_DOWNLOAD_PATH=/lib/firmware/ +DEV_NODE_TERIDIAN=ter10 + + # Show help +help() +{ + echo "Usage:" + echo " - $0 WAN-IF-NAME - start TAPIDEMO without FXO support" + echo " - $0 WAN-IF-NAME fxo - start TAPIDEMO with FXO support." + echo " - $0 stop - stop TAPIDEMO" +} + +# Check if device node for Teridian exists +checkFxoSupport() +{ + if [ ! -e /dev/$DEV_NODE_TERIDIAN ];then + echo "FXO support is disabled. Can not find required driver's device node." + else + TD_EXTRA_FLAGS_FXO="-x" + fi +} + +# Check if module drv_kpi2udp is loaded +checkKpi2UdpSupport() +{ + tmp=`cat /proc/modules | grep 'drv_kpi2udp '` + if [ "$tmp" != "" ]; then + TD_EXTRA_FLAGS_KPI2UDP="-q" + fi +} + +start() +{ + TD_WANIF=$1 + + TD_WANIF_IP=`ifconfig $TD_WANIF | grep 'inet addr:' | cut -f2 -d: | cut -f1 -d' '` + if [ "$TD_WANIF_IP" = "" ]; then + echo "Error, getting IP address for network device $TD_WANIF failed." + exit 1 + fi + + if [ "$2" = "" ];then + # FXO support is disabled. + continue + elif [ "$2" = "fxo" ];then + checkFxoSupport + else + echo "Error, unknown second parameter." + help + exit 1 + fi + + checkKpi2UdpSupport + + if [ -r /etc/rc.conf ]; then + . /etc/rc.conf + fi + + TD_DEBUG_LEVEL=$tapiDebugLevel + if [ "$TD_DEBUG_LEVEL" = "" ]; then + TD_DEBUG_LEVEL=3 + fi + + /usr/sbin/tapidemo -d $TD_DEBUG_LEVEL $TD_EXTRA_FLAGS_FXO $TD_EXTRA_FLAGS_KPI2UDP -i $TD_WANIF_IP -l $TD_DOWNLOAD_PATH & +} + +stop() +{ + killall tapidemo > /dev/null 2> /dev/null +} diff --git a/package/ltq-tapidemo/patches/100-ifxmips.patch b/package/ltq-tapidemo/patches/100-ifxmips.patch new file mode 100644 index 000000000..3dde8304f --- /dev/null +++ b/package/ltq-tapidemo/patches/100-ifxmips.patch @@ -0,0 +1,61 @@ +--- a/src/board_easy50712.c ++++ b/src/board_easy50712.c +@@ -32,7 +32,9 @@ + #ifdef OLD_BSP + #include "asm/danube/port.h" + #else +- #include "asm/ifx/ifx_gpio.h" ++#ifdef FXO ++# include "asm/ifx/ifx_gpio.h" ++#endif + #endif + + /* ============================= */ +--- a/src/board_easy508xx.c ++++ b/src/board_easy508xx.c +@@ -32,8 +32,6 @@ + #endif /* FXO */ + #include "pcm.h" + +-#include "asm/ifx/ifx_gpio.h" +- + #ifdef TD_DECT + #include "td_dect.h" + #endif /* TD_DECT */ +--- a/src/common.c ++++ b/src/common.c +@@ -7117,7 +7117,7 @@ IFX_return_t Common_GPIO_ClosePort(IFX_c + IFX_return_t Common_GPIO_ReservePin(IFX_int32_t nFd, IFX_int32_t nPort, + IFX_int32_t nPin, IFX_int32_t nModule) + { +-#ifndef OLD_BSP ++#if !defined(OLD_BSP) && defined(IFX_GPIO_IOC_PIN_RESERVE) + TD_PARAMETER_CHECK((NO_GPIO_FD >= nFd), nFd, IFX_ERROR); + + IFX_return_t nRet; +@@ -7155,7 +7155,7 @@ IFX_return_t Common_GPIO_ReservePin(IFX_ + IFX_return_t Common_GPIO_FreePin(IFX_int32_t nFd, IFX_int32_t nPort, + IFX_int32_t nPin, IFX_int32_t nModule) + { +-#ifndef OLD_BSP ++#if !defined(OLD_BSP) && defined(IFX_GPIO_IOC_PIN_RESERVE) + TD_PARAMETER_CHECK((NO_GPIO_FD >= nFd), nFd, IFX_ERROR); + + IFX_return_t nRet; +--- a/src/common.h ++++ b/src/common.h +@@ -79,12 +79,12 @@ + #ifdef OLD_BSP + #include "asm/danube/port.h" + #else +- #include "asm/ifx/ifx_gpio.h" ++ /*#include "asm/ifx/ifx_gpio.h"*/ + #endif + #endif + + #if (defined(AR9) || defined(VR9)) +- #include "asm/ifx/ifx_gpio.h" ++ /*#include "asm/ifx/ifx_gpio.h"*/ + #endif + + #ifdef TD_DECT diff --git a/package/ltq-tapidemo/patches/110-filename.patch b/package/ltq-tapidemo/patches/110-filename.patch new file mode 100644 index 000000000..73c2e977b --- /dev/null +++ b/package/ltq-tapidemo/patches/110-filename.patch @@ -0,0 +1,141 @@ +--- a/configure.in ++++ b/configure.in +@@ -1665,6 +1665,30 @@ AC_ARG_WITH(cflags, + ] + ) + ++dnl overwrite default FW file name ++AC_ARG_WITH(fw-file, ++ AS_HELP_STRING( ++ [--with-fw-file=val], ++ [overwrite default FW file name] ++ ), ++ [ ++ AC_MSG_RESULT([using firmware file $withval]) ++ AC_DEFINE_UNQUOTED([TD_FW_FILE], ["$withval"], [using firmware file]) ++ ] ++) ++ ++dnl overwrite default BBD file name ++AC_ARG_WITH(bbd-file, ++ AS_HELP_STRING( ++ [--with-bbd-file=val], ++ [overwrite default BBD file name] ++ ), ++ [ ++ AC_MSG_RESULT([using BBD file $withval]) ++ AC_DEFINE_UNQUOTED([TD_BBD_FILE], ["$withval"], [using BBD file]) ++ ] ++) ++ + AC_CONFIG_FILES([Makefile]) + AC_CONFIG_FILES([src/Makefile]) + +--- a/src/device_vmmc.c ++++ b/src/device_vmmc.c +@@ -49,40 +49,55 @@ + + + #ifdef USE_FILESYSTEM ++#ifdef TD_BBD_FILE ++ IFX_char_t* sBBD_CRAM_File_VMMC = TD_BBD_FILE; ++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = TD_BBD_FILE; ++#else ++ /** File holding coefficients. */ ++#ifdef DANUBE ++ /** Prepare file names for DANUBE */ ++ IFX_char_t* sBBD_CRAM_File_VMMC = "danube_bbd.bin"; ++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "danube_bbd_fxs.bin"; ++#elif AR9 ++ IFX_char_t* sBBD_CRAM_File_VMMC = "ar9_bbd.bin"; ++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "ar9_bbd_fxs.bin"; ++#elif VINAX ++ IFX_char_t* sBBD_CRAM_File_VMMC = "bbd.bin"; ++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = ""; ++#elif VR9 ++ IFX_char_t* sBBD_CRAM_File_VMMC = "vr9_bbd.bin"; ++ IFX_char_t* sBBD_CRAM_File_VMMC_Old = "vr9_bbd_fxs.bin"; ++#else ++#endif ++#endif /* TD_BBD_FILE */ ++#ifdef TD_FW_FILE ++ IFX_char_t* sPRAMFile_VMMC = TD_FW_FILE; ++ IFX_char_t* sPRAMFile_VMMC_Old = TD_FW_FILE; ++ IFX_char_t* sDRAMFile_VMMC = ""; ++#else + #ifdef DANUBE + /** Prepare file names for DANUBE */ + IFX_char_t* sPRAMFile_VMMC = "voice_danube_firmware.bin"; + IFX_char_t* sPRAMFile_VMMC_Old = "danube_firmware.bin"; + IFX_char_t* sDRAMFile_VMMC = ""; +- /** File holding coefficients. */ +- IFX_char_t* sBBD_CRAM_File_VMMC = "danube_bbd.bin"; +- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "danube_bbd_fxs.bin"; + #elif AR9 + /** Prepare file names for AR9 */ + IFX_char_t* sPRAMFile_VMMC = "voice_ar9_firmware.bin"; + IFX_char_t* sPRAMFile_VMMC_Old = "ar9_firmware.bin"; + IFX_char_t* sDRAMFile_VMMC = ""; +- /** File holding coefficients. */ +- IFX_char_t* sBBD_CRAM_File_VMMC = "ar9_bbd.bin"; +- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "ar9_bbd_fxs.bin"; + #elif VINAX + /** Prepare file names for VINAX */ + IFX_char_t* sPRAMFile_VMMC = "voice_vinax_firmware.bin"; + IFX_char_t* sPRAMFile_VMMC_Old = "firmware.bin"; + IFX_char_t* sDRAMFile_VMMC = ""; +- /** File holding coefficients. */ +- IFX_char_t* sBBD_CRAM_File_VMMC = "bbd.bin"; +- IFX_char_t* sBBD_CRAM_File_VMMC_Old = ""; + #elif VR9 + /** Prepare file names for VR9 */ + IFX_char_t* sPRAMFile_VMMC = "voice_vr9_firmware.bin"; + IFX_char_t* sPRAMFile_VMMC_Old = "vr9_firmware.bin"; + IFX_char_t* sDRAMFile_VMMC = ""; +- /** File holding coefficients. */ +- IFX_char_t* sBBD_CRAM_File_VMMC = "vr9_bbd.bin"; +- IFX_char_t* sBBD_CRAM_File_VMMC_Old = "vr9_bbd_fxs.bin"; + #else + #endif ++#endif /* TD_FW_FILE */ + #endif /* USE_FILESYSTEM */ + + /** Device names */ +--- a/src/common.c ++++ b/src/common.c +@@ -509,6 +509,10 @@ IFX_return_t Common_CheckDownloadPath(IF + if (IFX_TRUE != Common_FindBBD_CRAM(pCpuDevice, psPath, psFile)) + { + ret = IFX_ERROR; ++ if(bPrintTrace) ++ TRACE(TAPIDEMO, DBG_LEVEL_LOW, ++ ("Download path %s does not contain the required file %s.\n", ++ psPath, psFile)); + } + + if ((IFX_SUCCESS == ret) && +@@ -521,6 +525,10 @@ IFX_return_t Common_CheckDownloadPath(IF + { + ret = Common_CheckFileExists(psFile); + } ++ if(bPrintTrace && ret != IFX_SUCCESS) ++ TRACE(TAPIDEMO, DBG_LEVEL_LOW, ++ ("Download path %s does not contain the required file %s.\n", ++ psPath, psFile)); + } + #ifndef TAPI_VERSION4 + if (IFX_SUCCESS == ret) +@@ -532,13 +540,6 @@ IFX_return_t Common_CheckDownloadPath(IF + } + #endif + +- if (IFX_ERROR == ret) +- { +- if(bPrintTrace) +- TRACE(TAPIDEMO, DBG_LEVEL_LOW, +- ("Download path %s does not contain the required files.\n", +- psPath)); +- } + + return ret; + } /* Common_CheckDownloadPath */ diff --git a/package/ltq-vmmc/Config.in b/package/ltq-vmmc/Config.in new file mode 100644 index 000000000..691c60e48 --- /dev/null +++ b/package/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 + +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/ltq-vmmc/Makefile b/package/ltq-vmmc/Makefile new file mode 100644 index 000000000..51c33f57e --- /dev/null +++ b/package/ltq-vmmc/Makefile @@ -0,0 +1,160 @@ +# +# 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 + +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:=+kmod-ltq-tapi @TARGET_lantiq + FILES:=$(PKG_BUILD_DIR)/src/drv_vmmc.ko + AUTOLOAD:=$(call AutoLoad,25,drv_vmmc) + MAINTAINER:=John Crispin +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 + +ifeq ($(CONFIG_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) + $(CP) $(PKG_BUILD_DIR)/coef/$(COEF_SRC) $(1)/$(FW_DIR)/$(COEF_TARGET) +endef + +$(eval $(call KernelPackage,ltq-vmmc)) diff --git a/package/ltq-vmmc/files/vmmc.init b/package/ltq-vmmc/files/vmmc.init new file mode 100644 index 000000000..bae7badaf --- /dev/null +++ b/package/ltq-vmmc/files/vmmc.init @@ -0,0 +1,25 @@ +#!/bin/sh /etc/rc.common +# +# Activate Voice CPE TAPI subsystem LL driver for VMMC + +START=31 + +start() { + # TODO: clean up this mess + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Twinpass-VE" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 254 0 + return; + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` != "Danube" ] && { + [ ! -e /dev/amazon_s-port ] && mknod /dev/amazon_s-port c 240 1 + echo "INFO configuring HW scheduling 33/66" + echo "t0 0x0" > /proc/mips/mtsched + echo "t1 0x1" > /proc/mips/mtsched + echo "v0 0x0" > /proc/mips/mtsched + } + [ `cat /proc/cpuinfo | grep system | cut -f 3 -d ' '` = "Danube" ] && { + [ ! -e /dev/danube-port ] && mknod /dev/danube-port c 240 1 + # switch life-line relais + echo 1 > /sys/class/leds/fxs_relay/brightness + } +} diff --git a/package/ltq-vmmc/patches/000-portability.patch b/package/ltq-vmmc/patches/000-portability.patch new file mode 100644 index 000000000..48602476f --- /dev/null +++ b/package/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 + #include + #include ++#include + + #ifdef LINUX_2_6 + #include + #ifndef UTS_RELEASE ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++#include + #include ++#else ++#include ++#include ++#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 + + #ifdef CONFIG_DEBUG_MINI_BOOT + #define IKOS_MINI_BOOT + #endif /* */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + #include ++#ifndef UTS_RELEASE ++#include ++#endif ++#else ++#include ++#ifndef UTS_RELEASE ++#include ++#endif ++#endif + #include + #include + #include +@@ -34,7 +45,13 @@ + #include + #include + #ifdef LINUX_2_6 ++#ifndef UTS_RELEASE ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) + #include ++#else ++#include ++#endif ++#endif /* UTC_RELEASE */ + #else /* */ + #include + #include +@@ -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 ++#else ++#include ++#endif + #include + #include + +@@ -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 ++#else ++#include ++#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 + 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/ltq-vmmc/patches/100-target.patch b/package/ltq-vmmc/patches/100-target.patch new file mode 100644 index 000000000..eae621eaf --- /dev/null +++ b/package/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 ++#include ++ + #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 +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++ ++# 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 ++# include ++#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 +-#include +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++ ++ ++#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 ++# include ++# include ++#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 +-#include ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)) ++# include ++# include ++# include ++# include ++#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 ++# include ++#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 + #endif /* */ + +- ++#if !defined CONFIG_LANTIQ + #include + #include + #include ++#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/ltq-vmmc/patches/400-falcon.patch b/package/ltq-vmmc/patches/400-falcon.patch new file mode 100644 index 000000000..490d6e5dc --- /dev/null +++ b/package/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 ++#include ++#include ++#include ++#include ++#include ++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 + # include + #endif ++#if defined(SYSTEM_FALCON) ++#include ++#include ++#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 + # include + #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))